From eef525a9fd086801224d029d572d3ca7982705c2 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Wed, 9 Sep 2015 07:07:12 +0200 Subject: [PATCH 01/25] babel/eslint/tape boilerplate --- .eslintrc | 23 +- .gitignore | 4 +- CHANGELOG.md | 9 + README.md | 14 +- appveyor.yml | 5 +- package.json | 81 ++--- src/__tests__/api.js | 49 --- src/__tests__/benchmarks/index.css | 54 ---- src/__tests__/benchmarks/index.js | 34 --- src/__tests__/cases.js | 42 --- src/__tests__/cli.js | 279 ------------------ src/__tests__/cli.watcher.js | 146 --------- src/__tests__/fixtures/cases/color.css | 3 - .../fixtures/cases/color.expected.css | 4 - .../fixtures/cases/example.actual.css | 86 ------ src/__tests__/fixtures/cases/example.css | 73 ----- .../fixtures/cases/example.expected.css | 86 ------ .../fixtures/cases/plugin-options.css | 7 - .../cases/plugin-options.expected.css | 8 - src/__tests__/fixtures/cli.css | 8 - src/__tests__/fixtures/cli.error.css | 3 - src/__tests__/fixtures/cli.expected.css | 4 - .../fixtures/cli.watch-import-import.css | 1 - .../fixtures/cli.watch-import-import2.css | 1 - src/__tests__/fixtures/cli.watch-import.css | 1 - src/__tests__/fixtures/compress.css | 5 - .../fixtures/compress.default.expected.css | 1 - .../fixtures/compress.options.expected.css | 1 - src/__tests__/fixtures/config.css | 3 - src/__tests__/fixtures/config.expected.css | 3 - src/__tests__/fixtures/config.json | 9 - .../fixtures/features/autoprefixer.css | 8 - .../features/autoprefixer.expected.css | 14 - src/__tests__/fixtures/features/calc.css | 3 - .../fixtures/features/calc.expected.css | 3 - .../fixtures/features/color-function.css | 3 - .../features/color-function.expected.css | 3 - .../fixtures/features/color-gray.css | 3 - .../fixtures/features/color-gray.expected.css | 3 - .../fixtures/features/color-hex-alpha.css | 3 - .../features/color-hex-alpha.expected.css | 3 - src/__tests__/fixtures/features/color-hwb.css | 3 - .../fixtures/features/color-hwb.expected.css | 3 - .../fixtures/features/color-rebeccapurple.css | 3 - .../features/color-rebeccapurple.expected.css | 3 - .../fixtures/features/color-rgba.css | 4 - .../fixtures/features/color-rgba.expected.css | 6 - .../fixtures/features/custom-media.css | 5 - .../features/custom-media.expected.css | 5 - .../fixtures/features/custom-properties.css | 7 - .../features/custom-properties.expected.css | 5 - .../fixtures/features/custom-selectors.css | 5 - .../features/custom-selectors.expected.css | 8 - src/__tests__/fixtures/features/filter.css | 3 - .../fixtures/features/filter.expected.css | 4 - .../fixtures/features/font-variant.css | 7 - .../features/font-variant.expected.css | 9 - .../fixtures/features/media-queries-range.css | 2 - .../features/media-queries-range.expected.css | 2 - .../features/pseudo-class-any-link.css | 3 - .../pseudo-class-any-link.expected.css | 3 - .../features/pseudo-class-matches.css | 3 - .../pseudo-class-matches.expected.css | 3 - .../fixtures/features/pseudo-class-not.css | 3 - .../features/pseudo-class-not.expected.css | 3 - .../fixtures/features/pseudo-elements.css | 6 - .../features/pseudo-elements.expected.css | 6 - src/__tests__/fixtures/features/rem.css | 11 - .../fixtures/features/rem.expected.css | 12 - src/__tests__/fixtures/import.css | 5 - .../fixtures/import.default.expected.css | 7 - src/__tests__/fixtures/import.imported.css | 3 - .../fixtures/import.options.expected.css | 9 - src/__tests__/fixtures/sourcemap.css | 5 - .../fixtures/sourcemap.expected-start | 1 - src/__tests__/fixtures/sourcemap.expected.css | 9 - src/__tests__/fixtures/sourcemap.imported.css | 3 - src/__tests__/fixtures/url.css | 1 - .../fixtures/url.default.expected.css | 6 - .../fixtures/url.options.expected.css | 6 - src/__tests__/fixtures/url/assets/font.woff | Bin 19616 -> 0 bytes src/__tests__/fixtures/url/assets/pixel.gif | Bin 67 -> 0 bytes src/__tests__/fixtures/url/dep.css | 6 - src/__tests__/index.js | 12 + src/__tests__/messages/index.js | 45 --- src/__tests__/option.browsers.js | 65 ---- src/__tests__/option.compress.js | 50 ---- src/__tests__/option.features.js | 76 ----- src/__tests__/option.import.js | 54 ---- src/__tests__/option.messages.js | 84 ------ src/__tests__/option.plugins.js | 25 -- src/__tests__/option.sourcemap.js | 46 --- src/__tests__/option.url.js | 32 -- src/__tests__/prevent-webpack-usage.js | 51 ---- src/__tests__/utils/index.js | 95 ------ src/__tests__/utils/isBabel.js | 1 - src/bin.js | 224 -------------- src/features-activation-map.js | 29 -- src/features.js | 60 ---- src/fixes/custom-selectors-missing-colon.js | 41 --- src/fixes/index.js | 5 - src/index.js | 197 +------------ src/option.messages.browser.styles.js | 52 ---- src/option.messages.js | 47 --- src/plugins/messages.js | 104 ------- 105 files changed, 77 insertions(+), 2609 deletions(-) delete mode 100644 src/__tests__/api.js delete mode 100644 src/__tests__/benchmarks/index.css delete mode 100644 src/__tests__/benchmarks/index.js delete mode 100644 src/__tests__/cases.js delete mode 100644 src/__tests__/cli.js delete mode 100644 src/__tests__/cli.watcher.js delete mode 100755 src/__tests__/fixtures/cases/color.css delete mode 100755 src/__tests__/fixtures/cases/color.expected.css delete mode 100644 src/__tests__/fixtures/cases/example.actual.css delete mode 100644 src/__tests__/fixtures/cases/example.css delete mode 100644 src/__tests__/fixtures/cases/example.expected.css delete mode 100644 src/__tests__/fixtures/cases/plugin-options.css delete mode 100644 src/__tests__/fixtures/cases/plugin-options.expected.css delete mode 100755 src/__tests__/fixtures/cli.css delete mode 100644 src/__tests__/fixtures/cli.error.css delete mode 100755 src/__tests__/fixtures/cli.expected.css delete mode 100644 src/__tests__/fixtures/cli.watch-import-import.css delete mode 100644 src/__tests__/fixtures/cli.watch-import-import2.css delete mode 100644 src/__tests__/fixtures/cli.watch-import.css delete mode 100755 src/__tests__/fixtures/compress.css delete mode 100644 src/__tests__/fixtures/compress.default.expected.css delete mode 100644 src/__tests__/fixtures/compress.options.expected.css delete mode 100644 src/__tests__/fixtures/config.css delete mode 100644 src/__tests__/fixtures/config.expected.css delete mode 100644 src/__tests__/fixtures/config.json delete mode 100755 src/__tests__/fixtures/features/autoprefixer.css delete mode 100755 src/__tests__/fixtures/features/autoprefixer.expected.css delete mode 100755 src/__tests__/fixtures/features/calc.css delete mode 100755 src/__tests__/fixtures/features/calc.expected.css delete mode 100755 src/__tests__/fixtures/features/color-function.css delete mode 100755 src/__tests__/fixtures/features/color-function.expected.css delete mode 100644 src/__tests__/fixtures/features/color-gray.css delete mode 100644 src/__tests__/fixtures/features/color-gray.expected.css delete mode 100755 src/__tests__/fixtures/features/color-hex-alpha.css delete mode 100755 src/__tests__/fixtures/features/color-hex-alpha.expected.css delete mode 100644 src/__tests__/fixtures/features/color-hwb.css delete mode 100755 src/__tests__/fixtures/features/color-hwb.expected.css delete mode 100755 src/__tests__/fixtures/features/color-rebeccapurple.css delete mode 100755 src/__tests__/fixtures/features/color-rebeccapurple.expected.css delete mode 100644 src/__tests__/fixtures/features/color-rgba.css delete mode 100644 src/__tests__/fixtures/features/color-rgba.expected.css delete mode 100755 src/__tests__/fixtures/features/custom-media.css delete mode 100755 src/__tests__/fixtures/features/custom-media.expected.css delete mode 100755 src/__tests__/fixtures/features/custom-properties.css delete mode 100755 src/__tests__/fixtures/features/custom-properties.expected.css delete mode 100644 src/__tests__/fixtures/features/custom-selectors.css delete mode 100644 src/__tests__/fixtures/features/custom-selectors.expected.css delete mode 100644 src/__tests__/fixtures/features/filter.css delete mode 100644 src/__tests__/fixtures/features/filter.expected.css delete mode 100644 src/__tests__/fixtures/features/font-variant.css delete mode 100644 src/__tests__/fixtures/features/font-variant.expected.css delete mode 100644 src/__tests__/fixtures/features/media-queries-range.css delete mode 100644 src/__tests__/fixtures/features/media-queries-range.expected.css delete mode 100644 src/__tests__/fixtures/features/pseudo-class-any-link.css delete mode 100644 src/__tests__/fixtures/features/pseudo-class-any-link.expected.css delete mode 100644 src/__tests__/fixtures/features/pseudo-class-matches.css delete mode 100644 src/__tests__/fixtures/features/pseudo-class-matches.expected.css delete mode 100644 src/__tests__/fixtures/features/pseudo-class-not.css delete mode 100644 src/__tests__/fixtures/features/pseudo-class-not.expected.css delete mode 100644 src/__tests__/fixtures/features/pseudo-elements.css delete mode 100644 src/__tests__/fixtures/features/pseudo-elements.expected.css delete mode 100644 src/__tests__/fixtures/features/rem.css delete mode 100644 src/__tests__/fixtures/features/rem.expected.css delete mode 100755 src/__tests__/fixtures/import.css delete mode 100755 src/__tests__/fixtures/import.default.expected.css delete mode 100755 src/__tests__/fixtures/import.imported.css delete mode 100755 src/__tests__/fixtures/import.options.expected.css delete mode 100644 src/__tests__/fixtures/sourcemap.css delete mode 100644 src/__tests__/fixtures/sourcemap.expected-start delete mode 100755 src/__tests__/fixtures/sourcemap.expected.css delete mode 100755 src/__tests__/fixtures/sourcemap.imported.css delete mode 100644 src/__tests__/fixtures/url.css delete mode 100644 src/__tests__/fixtures/url.default.expected.css delete mode 100644 src/__tests__/fixtures/url.options.expected.css delete mode 100644 src/__tests__/fixtures/url/assets/font.woff delete mode 100644 src/__tests__/fixtures/url/assets/pixel.gif delete mode 100644 src/__tests__/fixtures/url/dep.css create mode 100644 src/__tests__/index.js delete mode 100644 src/__tests__/messages/index.js delete mode 100644 src/__tests__/option.browsers.js delete mode 100644 src/__tests__/option.compress.js delete mode 100644 src/__tests__/option.features.js delete mode 100644 src/__tests__/option.import.js delete mode 100644 src/__tests__/option.messages.js delete mode 100644 src/__tests__/option.plugins.js delete mode 100644 src/__tests__/option.sourcemap.js delete mode 100644 src/__tests__/option.url.js delete mode 100644 src/__tests__/prevent-webpack-usage.js delete mode 100644 src/__tests__/utils/index.js delete mode 100644 src/__tests__/utils/isBabel.js delete mode 100755 src/bin.js delete mode 100644 src/features-activation-map.js delete mode 100644 src/features.js delete mode 100644 src/fixes/custom-selectors-missing-colon.js delete mode 100644 src/fixes/index.js delete mode 100644 src/option.messages.browser.styles.js delete mode 100644 src/option.messages.js delete mode 100644 src/plugins/messages.js diff --git a/.eslintrc b/.eslintrc index 1b4bd1c..a7d1082 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,8 @@ --- -# babel support more syntax stuff than eslint for now +root: true +extends: eslint:recommended + +# babel-eslint support more syntax stuff than eslint for now parser: babel-eslint ecmaFeatures: @@ -27,31 +30,33 @@ plugins: # 0: off, 1: warning, 2: error rules: + no-console: 0 + indent: [2, 2] # 2 spaces indentation max-len: [2, 80, 4] - no-multiple-empty-lines: [2, {"max": 1}] quotes: [2, "double"] semi: [2, "never"] + no-multiple-empty-lines: [2, {"max": 1}] brace-style: [2, "stroustrup"] comma-dangle: [2, "always-multiline"] comma-style: [2, "last"] - computed-property-spacing: [2, "never"] dot-location: [2, "property"] - no-var: [2] - no-bitwise: [2] one-var: [2, "never"] + no-var: [2] prefer-const: [2] + no-bitwise: [2] + + object-curly-spacing: [2, "always"] + array-bracket-spacing: [2, "always"] + #computed-property-spacing: [2, "always"] - array-bracket-spacing: [2, "never"] - object-shorthand: [2, "methods"] - object-curly-spacing: [2, "never"] + space-unary-ops: [2, {"words": true, "nonwords": false}] space-after-keywords: [2, "always"] space-before-blocks: [2, "always"] space-before-function-paren: [2, "never"] space-in-parens: [2, "never"] - space-unary-ops: [2, {"words": true, "nonwords": false}] spaced-comment: [2, "always"] # see globals diff --git a/.gitignore b/.gitignore index b0ecf2b..06b6d80 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ +# npm node_modules -dist +# build +lib docs/dist diff --git a/CHANGELOG.md b/CHANGELOG.md index c63fde7..20bc48c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# 2.0.0 - Unreleased + +- Added: support for PostCSS v5.x +- Removed: support for PostCSS v4.x + +--- + +**pre 2.0.0 information was related to `cssnext` package.** + # 1.8.4 - 2015-08-24 - Fixed: `compress` option now works again correctly. A recent update in cssnano diff --git a/README.md b/README.md index 6e3cdce..3e3f200 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,19 @@ -# cssnext +# postcss-cssnext -[![NPM version](http://img.shields.io/npm/v/cssnext.svg?style=flat)](https://www.npmjs.org/package/cssnext) -[![Travis Build Status](https://img.shields.io/travis/cssnext/cssnext.svg?label=unix%20build)](https://travis-ci.org/cssnext/cssnext) -[![AppVeyor Build Status](https://img.shields.io/appveyor/ci/MoOx/cssnext.svg?label=windows%20build)](https://ci.appveyor.com/project/MoOx/cssnext) +[![NPM version](http://img.shields.io/npm/v/postcss-cssnext.svg?style=flat)](https://www.npmjs.org/package/postcss-cssnext) +[![Travis Build Status](https://img.shields.io/travis/cssnext/postcss-cssnext.svg?label=unix%20build)](https://travis-ci.org/cssnext/postcss-cssnext) +[![AppVeyor Build Status](https://img.shields.io/appveyor/ci/MoOx/postcss-cssnext.svg?label=windows%20build)](https://ci.appveyor.com/project/MoOx/postcss-cssnext) [![Join the chat at https://gitter.im/cssnext/cssnext](https://img.shields.io/badge/gitter%20-join%20chat%20%E2%9E%9E-1dce73.svg)](https://gitter.im/cssnext/cssnext) > Use tomorrow's CSS syntax, today. cssnext is a CSS transpiler that allows you to use the latest CSS syntax today. -It transforms CSS specs into more compatible CSS so you don’t need to wait for browser support. +It transforms CSS specs into more compatible CSS so you don’t need to wait for browser support. + +**This repository contains the PostCSS plugin.** + +--- ## Check out [cssnext website](http://cssnext.io/) diff --git a/appveyor.yml b/appveyor.yml index be1c2ed..336e1af 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,6 +9,8 @@ environment: version: "{build}" build: off deploy: off +matrix: + fast_finish: true install: - ps: Install-Product node $env:nodejs_version @@ -17,5 +19,4 @@ install: test_script: - node --version - npm --version - - ps: "npm test # PowerShell" - - cmd: "npm test" + - npm test diff --git a/package.json b/package.json index 7bc5ed9..a74ed1d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "cssnext", - "version": "1.8.4", + "name": "postcss-cssnext", + "version": "2.0.0", "description": "Use tomorrow's CSS syntax, today", "keywords": [ "css", @@ -17,61 +17,23 @@ ], "author": "Maxime Thirouin", "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/cssnext/cssnext.git" - }, + "repository": "https://github.com/cssnext/postcss-cssnext.git", "homepage": "http://cssnext.io/", - "bugs": { - "url": "https://github.com/cssnext/cssnext/issues" - }, - "main": "dist/index.js", - "bin": { - "cssnext": "dist/bin.js" - }, + "main": "lib/index.js", + "files": [ + "lib", + "src", + "!**/__tests__" + ], "dependencies": { - "autoprefixer-core": "^5.0.0", - "caniuse-api": "^1.3.1", - "chalk": "^1.0.0", - "chokidar": "^1.0.0", - "commander": "^2.3.0", - "cssnano": "^2.6.1", - "exit": "^0.1.2", - "mkdirp": "^0.5.1", - "pixrem": "^1.1.0", - "pleeease-filters": "^1.0.0", - "postcss": "^4.0.2", - "postcss-calc": "^4.0.0", - "postcss-color-function": "^1.1.0", - "postcss-color-gray": "^2.0.0", - "postcss-color-hex-alpha": "^1.1.0", - "postcss-color-hwb": "^1.1.0", - "postcss-color-rebeccapurple": "^1.1.0", - "postcss-color-rgba-fallback": "^1.0.0", - "postcss-custom-media": "^4.0.0", - "postcss-custom-properties": "^4.0.0", - "postcss-custom-selectors": "^2.3.0", - "postcss-font-variant": "^1.0.0", - "postcss-import": "^6.0.0", - "postcss-media-minmax": "^1.1.0", - "postcss-messages": "^0.2.2", - "postcss-pseudo-class-any-link": "^0.2.1", - "postcss-pseudoelements": "^2.1.1", - "postcss-reporter": "^0.1.0", - "postcss-selector-matches": "^1.2.1", - "postcss-selector-not": "^1.0.1", - "postcss-url": "^4.0.1", - "read-file-stdin": "^0.2.0", - "to-slug-case": "^0.1.2", - "to-space-case": "^0.1.3", - "write-file-stdout": "0.0.2" + "postcss": "^5.0.4" }, "devDependencies": { - "babel": "^5.4.7", + "babel": "^5.8.23", "babel-core": "^5.4.7", - "babel-eslint": "^3.1.17", + "babel-eslint": "^4.1.1", "babel-loader": "^5.1.3", - "babel-tape-runner": "^1.1.0", + "babel-tape-runner": "^1.2.0", "classnames": "^2.1.1", "css-loader": "^0.13.1", "cssnext-loader": "^1.0.1", @@ -80,7 +42,7 @@ "cssrecipes-grid": "^0.4.0", "cssrecipes-utils": "^0.5.0", "cssrecipes-vertical-rhythm": "^0.6.0", - "eslint": "^1.0.0", + "eslint": "^1.3.1", "eslint-loader": "^1.0.0", "eslint-plugin-react": "^3.0.0", "extract-text-webpack-plugin": "^0.8.0", @@ -107,27 +69,26 @@ "object-assign": "^3.0.0", "opn": "^1.0.2", "react": "^0.13.3", - "rimraf": "^2.3.4", + "rimraf": "^2.4.3", "style-loader": "^0.12.2", - "tape": "^4.0.0", + "tape": "^4.2.0", "webpack": "^1.9.7", "webpack-dev-server": "^1.8.2", "webpack-nano-logs": "^1.0.0" }, "scripts": { - "prebabelify": "rimraf dist", - "babelify": "babel src --out-dir dist", + "prebabelify": "rimraf lib", + "babelify": "babel src --out-dir lib", "prepublish": "npm run babelify", - "standalone": "webpack --output-library-target umd --output-library cssnext dist/index.js dist/cssnext.js", "#lint": "even if there is a .eslintignore symlink, we use an explicit command because windows don't like unix symlink", "lint": "eslint --ignore-path .gitignore .", "#tape": "to avoid really slow tests, we run babel once & run tests on the result", - "tape": "tape 'dist/__tests__/*.js'", - "test": "npm run lint && npm run babelify && npm run standalone && npm run tape", + "tape": "tape 'lib/__tests__/*.js'", + "test": "npm run lint && npm run babelify && npm run tape", "docs-build": "babel-node docs/scripts/build", "docs-start": "npm run docs-build -- --dev --dev-server --open", "docs-test": "npm run docs-build -- --production", - "_docs-deploy": "GIT_DEPLOY_DIR=docs/dist ./docs/scripts/deploy-to-gh-pages.sh -v", + "_docs-deploy": "GIT_DEPLOY_DIR=docs/lib ./docs/scripts/deploy-to-gh-pages.sh -v", "docs-deploy": "npm run docs-test && npm run _docs-deploy" } } diff --git a/src/__tests__/api.js b/src/__tests__/api.js deleted file mode 100644 index 479f059..0000000 --- a/src/__tests__/api.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Test dependencies - */ -const test = require("tape") - -const utils = require("./utils") -const cssnext = require("..") -const postcss = require("postcss") - -/** - * Global API tests - */ -test("cssnext API", function(t) { - const input = utils.readFixture("cases/example") - const output = utils.readFixture("cases/example.expected") - - // simple API strings + options - t.ok( - typeof cssnext("html{}") === "string", - "should return a string" - ) - t.ok( - typeof cssnext("") === "string", - "should return a string, even if the given string is empty" - ) - utils.compareFixtures( - t, - "cases/example", - "simple example with multiples features should work with cssnext API" - ) - - // as a postcss plugin - const postcssInstance = cssnext() - t.ok( - typeof postcssInstance === "object" && postcssInstance.process, - "should return a postcss instance" - ) - t.equal( - postcss().use(cssnext()).process(input).css, - output, - "simple example with multiples features should work with postcss API" - ) - - const opts = {} - cssnext("html{}", opts) - t.ok(!opts.hasOwnProperty("map"), "doesn't mutate options object") - - t.end() -}) diff --git a/src/__tests__/benchmarks/index.css b/src/__tests__/benchmarks/index.css deleted file mode 100644 index 09f942a..0000000 --- a/src/__tests__/benchmarks/index.css +++ /dev/null @@ -1,54 +0,0 @@ -/* custom properties */ -:root { - --fontSize: 1rem; - --mainColor: #12345678; - --highlightColor: hwb(190, 35%, 20%); -} - -/* custom media queries */ -@custom-media --viewport-medium (width <= 50em); - -/* some var() & calc() */ -body { - color: var(--mainColor); - - font-size: var(--fontSize); - line-height: calc(var(--fontSize) * 1.5); - padding: calc((var(--fontSize) / 2) + 1px); -} - -/* custom media query usage */ -@media (--viewport-medium) { - body { font-size: calc(var(--fontSize) * 1.2); } - /* no need for px here since browsers that supports media queries support rem already */ -} - -/* custom selectors */ -@custom-selector --heading h1, h2, h3, h4, h5, h6; ---heading { margin-top: 0 } - -/* colors stuff */ -a { - color: var(--highlightColor); - transition: color 1s; /* autoprefixed ! */ -} -a:hover { color: gray(255, 50%) } -a:active { color: rebeccapurple } -a:visited { color: color(red blackness(+20%)) } - -/* font stuff */ -h2 { - font-variant-caps: small-caps; -} - -table { - font-variant-numeric: lining-nums; -} - -/* filters */ -.blur { - filter: blur(4px); -} -.sepia { - filter: sepia(.8); -} diff --git a/src/__tests__/benchmarks/index.js b/src/__tests__/benchmarks/index.js deleted file mode 100644 index a959ff5..0000000 --- a/src/__tests__/benchmarks/index.js +++ /dev/null @@ -1,34 +0,0 @@ -const cssnext = require("../") -const t = require("microtime") - -let input = require("fs").readFileSync( - "./src/__tests__/benchmarks.css", - {encoding: "utf8"} -) - -// make a 2MB input -for (let i = 0; i <= 10; i++) { - input += input -} -// check the real input -// require("fs").writeFileSync("./src/__tests__/fixtures/bench.css", input) - -// test each features -const keys = Object.keys(cssnext.features) -const allOff = {} - -keys.forEach(function(k) { - allOff[k] = false -}) - -console.log("Each features is tested on a 2MB input (>100 000 lines)\n") - -keys.forEach(function(k) { - const enable = {...allOff} - enable[k] = true - const start = t.now() - cssnext(input, {features: enable}) - const stop = t.now() - - console.log(k + " takes " + ((stop - start) / 1000000) + "s") // , enable) -}) diff --git a/src/__tests__/cases.js b/src/__tests__/cases.js deleted file mode 100644 index bac0919..0000000 --- a/src/__tests__/cases.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Test dependencies - */ -const test = require("tape") - -const utils = require("./utils") -const cssnext = require("..") - -/** - * Use cases test - */ -test("use case: color plugins together", function(t) { - t.equal( - cssnext( - utils.readFixture("cases/color"), - {} - ), - utils.readFixture("cases/color.expected"), - "all color plugins should works together" - ) - - t.end() -}) - -test("use case: use plugin options", function(t) { - t.equal( - cssnext( - utils.readFixture("cases/plugin-options"), - { - features: { - customProperties: { - preserve: true, - }, - }, - } - ), - utils.readFixture("cases/plugin-options.expected"), - "should be able to pass options to plugins" - ) - - t.end() -}) diff --git a/src/__tests__/cli.js b/src/__tests__/cli.js deleted file mode 100644 index ba582c7..0000000 --- a/src/__tests__/cli.js +++ /dev/null @@ -1,279 +0,0 @@ -/** - * Test dependencies - */ -import {exec} from "child_process" - -import test from "tape" - -import utils from "./utils" -import cssnext from ".." - -import isBabel from "./utils/isBabel" - -/** - * CLI tests - */ -const input = utils.readFixture("cli") -const output = utils.readFixture("cli.expected") - -// node bin is used to help for windows -const cssnextBin = isBabel ? "babel-node src/bin" : "node dist/bin" - -test("cli", function(t) { - let planned = 0 - - exec( - cssnextBin + - " src/__tests__/fixtures/cli.css" + - " src/__tests__/fixtures/cli.output--io.css", - function(err) { - if (err) { - throw err - } - const res = utils.readFixture("cli.output--io") - t.equal(res, output, "should read from a file and write to a file") - utils.remove("cli.output--io") - } - ) - planned += 1 - - exec( - cssnextBin + - " src/__tests__/fixtures/cli.css" + - " src/__tests__/fixtures/cli/output--io.css", - function(err) { - if (err) { - throw err - } - const res = utils.readFixture("cli/output--io") - t.equal( - res, - "body {\n color: #e00;\n background: url(../url);\n}\n", - "should rebase url" - ) - utils.remove("cli/output--io") - } - ) - planned += 1 - - exec(cssnextBin + " src/__tests__/fixtures/cli.css", function(err, stdout) { - if (err) { - throw err - } - t.equal( - stdout, - output, "should read from a file and write to stdout" - ) - }) - planned += 1 - - const childProcess = exec(cssnextBin, function(err, stdout) { - if (err) { - throw err - } - t.equal(stdout, output, "should read from stdin and write to stdout") - }) - childProcess.stdin.write(new Buffer(input)) - childProcess.stdin.end() - planned += 1 - - exec( - cssnextBin + " src/__tests__/fixtures/cli.dont-exist.css", - function(err, stdout, stderr) { - t.ok( - err && err.code === 1, - "should return an error when input file is unreadable" - ) - t.ok( - utils.contains(stderr, "Unable to read file"), - "should show that the input file is not found" - ) - } - ) - planned += 2 - - exec( - cssnextBin + " src/__tests__/fixtures/cli.error.css", - function(err, stdout, stderr) { - t.ok(err && err.code === 2, "should throw an error") - t.ok( - utils.contains(stderr, "encounters an error"), - "should output a readable error") - t.ok( - utils.contains( - stderr, - "If this error looks like a bug, please report it here" - ), - "should show the url where to report bugs" - ) - }) - planned += 3 - - exec( - cssnextBin + - " --config src/__tests__/fixtures/config.json" + - " src/__tests__/fixtures/config.css", - function(err, stdout) { - if (err) { - throw err - } - t.equal( - stdout, - utils.readFixture("config.expected"), - "should read config file on --config" - ) - }) - planned += 1 - - const noCustomPropInput = ":root{--foo:bar}baz{qux:var(--foo)}" - const childProcessBrowsers = exec( - cssnextBin + " --browsers \"Firefox >= 31\"", - function(err, stdout) { - if (err) { - throw err - } - t.equal(stdout, noCustomPropInput, "should have a --browsers option") - }) - childProcessBrowsers.stdin.write(new Buffer(noCustomPropInput)) - childProcessBrowsers.stdin.end() - planned += 1 - - exec( - cssnextBin + - " --verbose src/__tests__/fixtures/cli.css" + - " src/__tests__/fixtures/cli.output--verbose.css" - , - function(err, stdout) { - if (err) { - throw err - } - t.ok(utils.contains(stdout, "Output written"), "should log on --verbose") - utils.remove("cli.output--verbose") - } - ) - planned += 1 - - exec( - cssnextBin + " --no-import src/__tests__/fixtures/import.css", - function(err, stdout) { - if (err) { - throw err - } - t.equal( - stdout, - utils.readFixture("import"), - "should not import on --no-import" - ) - }) - planned += 1 - - exec( - cssnextBin + " --no-url src/__tests__/fixtures/url.css", - {cwd: process.cwd()}, - function(err, stdout) { - if (err) { - throw err - } - t.equal( - stdout, - utils.readFixture("url/dep"), - "should not adjust url on --no-url" - ) - } - ) - planned += 1 - - exec( - cssnextBin + " --compress src/__tests__/fixtures/compress.css", - function(err, stdout) { - if (err) { - throw err - } - t.equal( - stdout.trim(), - utils.readFixture("compress.default.expected").trim(), - "should compress on --compress" - ) - } - ) - planned += 1 - - exec( - cssnextBin + " --sourcemap src/__tests__/fixtures/sourcemap.css", - function(err, stdout) { - if (err) { - throw err - } - t.ok( - stdout - .indexOf("/*# sourceMappingURL=data:application/json;base64,") - > -1 - , - "should add sourcemap on --sourcemap" - ) - } - ) - planned += 1 - - const toSpace = require("to-space-case") - const toSlug = require("to-slug-case") - const features = Object.keys(cssnext.features) - const no = "--no-" + features.map(function(feature) { - return toSlug(feature) - }).join(" --no-") - features.forEach(function(feature) { - const slug = toSlug(feature) - const featureOutput = utils.readFixture("features/" + slug) - exec( - cssnextBin + " " + no + - " src/__tests__/fixtures/features/" + slug + ".css", - function(err, stdout) { - if (err) { - throw err - } - t.equal( - stdout, - featureOutput, - "should not modify input of '" + toSpace(feature) + - "' fixture if all features are disabled" - ) - } - ) - }) - planned += features.length - - exec( - cssnextBin + " --watch", - function(err, stdout, stderr) { - t.ok(err && err.code === 3, - "should return an error when or are missing when " + - "`--watch` option passed" - ) - t.ok( - utils.contains(stderr, "--watch option need"), - "should show an explanation when or are missing when" + - " `--watch` option passed" - ) - } - ) - planned += 2 - - exec( - cssnextBin + " --watch src/__tests__/fixtures/cli.css", - function(err, stdout, stderr) { - t.ok( - err && err.code === 3, - "should return an error when is missing when `--watch`" + - "option passed" - ) - t.ok( - utils.contains(stderr, "--watch option need"), - "should show an explanation when is missing when `--watch` " + - "option passed" - ) - } - ) - planned += 2 - - t.plan(planned) -}) diff --git a/src/__tests__/cli.watcher.js b/src/__tests__/cli.watcher.js deleted file mode 100644 index ef83dc9..0000000 --- a/src/__tests__/cli.watcher.js +++ /dev/null @@ -1,146 +0,0 @@ -/** - * Test dependencies - */ -import {exec, spawn} from "child_process" -import fs from "fs" - -import test from "tape" - -import utils from "./utils" - -import isBabel from "./utils/isBabel" - -// I don't success to call the kill() process from node and both Travis CI and -// Appveyor so we avoid this test on this environnements -if (!(process.env.TRAVIS || process.env.APPVEYOR)) { - // node bin is used to help for windows - const nodeBin = isBabel ? "babel-node" : "node" - const cssnextBin = isBabel ? "src/bin" : "dist/bin" - - test("cli/watcher", function(t) { - let planned = 0 - - const watchProcess = exec( - `${ nodeBin } ${ cssnextBin }` + - " --watch src/__tests__/fixtures/cli.error.css" + - " src/__tests__/fixtures/cli.output--watch.css", - function(err) { - t.ok( - err && err.signal === "SIGTERM", - "should only be killed by an interrupt when `--watch` option passed" - ) - if (err && !err.killed) { - throw err - } - } - ) - - const msgWatch = "should output error messages when `--watch` option passed" - const watchTimeout = setTimeout(function() { - t.fail(msgWatch) - watchProcess.kill() - }, 5000) - watchProcess.stderr.on("data", function(data) { - if (utils.contains(data, "encounters an error")) { - t.pass(msgWatch) - clearTimeout(watchTimeout) - watchProcess.kill() - } - }) - planned += 2 - - // watch/import tests - const watchOut = "src/__tests__/fixtures/cli.output--watch-import.css" - - const watchImportProcess = spawn( - nodeBin, - [ - cssnextBin, - // "--verbose", - "--watch", - "src/__tests__/fixtures/cli.watch-import.css", - watchOut, - ], - {stdio: "inherit"} - ) - - // watch an empty file doesn't seems to work great, so I am using - // /**/ to get a content - // yeah... - - // trigger a change in cli.import.css to add a new watched file - // cli.import2.css - fs.writeFileSync( - "src/__tests__/fixtures/cli.watch-import.css", - "/**/ " + - "@import 'cli.watch-import-import.css';" + - "@import 'cli.watch-import-import2.css';" - ) - - // we are using setTimeout for the watcher to do his job - setTimeout(function() { - // check the output has been updated (watcher works) - t.equal( - fs.readFileSync( - watchOut, - {encoding: "utf8"} - ), - "/**/ watch{}er{}", - "should update the file" - ) - - // remove this newly imported file - fs.writeFileSync("src/__tests__/fixtures/cli.watch-import.css", "/**/") - - // check the output has been update - setTimeout(function() { - t.equal( - fs.readFileSync( - watchOut, - {encoding: "utf8"} - ), - "/**/", - "should update the file, again" - ) - - setTimeout(function() { - // previously imported file should not be watched anymore - // to check that we read output mtime, modify the file that should not - // be watched and check back that the output file has the same mtime - - // trigger a change in previously imported file - const now = (new Date()).getTime() - fs.utimesSync( - "src/__tests__/fixtures/cli.watch-import-import.css", - now, - now - ) - - // not sure why but it's better with the statSync on the watched file - // in this delayed call - setTimeout(function() { - const outStat = fs.statSync(watchOut) - - setTimeout(function() { - // this time, it should not trigger anything - const outStatAfter = fs.statSync(watchOut) - t.equal( - outStat.mtime.getTime(), - outStatAfter.mtime.getTime(), - "should not modify a file if a previously imported file is " + - "modified" - ) - - utils.remove("cli.output--watch-import") - watchImportProcess.kill() - }, 1000) - }, 1000) - }, 1000) - }, 1000) - }, 1000) - - planned += 3 - - t.plan(planned) - }) -} diff --git a/src/__tests__/fixtures/cases/color.css b/src/__tests__/fixtures/cases/color.css deleted file mode 100755 index c239483..0000000 --- a/src/__tests__/fixtures/cases/color.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: rgb(102, 51, 153) linear-gradient(color(rebeccapurple a(50%)), hwb(0, 20%, 40%), color(hwb(0, 20%, 40%, .5) a(+10%)), color(#9d9c a(90%))); -} diff --git a/src/__tests__/fixtures/cases/color.expected.css b/src/__tests__/fixtures/cases/color.expected.css deleted file mode 100755 index 39d9bc5..0000000 --- a/src/__tests__/fixtures/cases/color.expected.css +++ /dev/null @@ -1,4 +0,0 @@ -body { - background: rgb(102, 51, 153) -webkit-linear-gradient(rgba(102, 51, 153, 0.5), rgb(153, 51, 51), rgba(153, 51, 51, 0.55), rgba(153, 221, 153, 0.9)); - background: rgb(102, 51, 153) linear-gradient(rgba(102, 51, 153, 0.5), rgb(153, 51, 51), rgba(153, 51, 51, 0.55), rgba(153, 221, 153, 0.9)); -} diff --git a/src/__tests__/fixtures/cases/example.actual.css b/src/__tests__/fixtures/cases/example.actual.css deleted file mode 100644 index d605897..0000000 --- a/src/__tests__/fixtures/cases/example.actual.css +++ /dev/null @@ -1,86 +0,0 @@ -/* custom properties */ - -/* custom media queries */ - -/* some var() & calc() */ -body { - color: #123456; - color: rgba(18, 52, 86, 0.47059); - - font-size: 16px; - font-size: 1rem; - line-height: 24px; - line-height: 1.5rem; - padding: calc(0.5rem + 1px); -} - -/* custom media query usage */ -@media (max-width: 50em) { - body { font-size: 1.2rem; } - /* no need for px here since browsers that supports media queries support rem already */ -} - -/* custom selectors */ -h1, -h2, -h3, -h4, -h5, -h6 { margin-top: 0 } - -/* colors stuff */ -a { - color: rgb(89, 185, 204); - -webkit-transition: color 1s; - transition: color 1s; /* autoprefixed ! */ -} -a:hover { color: #FFFFFF; color: rgba(255, 255, 255, 0.5) } -a:active { color: rgb(102, 51, 153) } -a:link,a:visited { color: rgb(89, 142, 153) } - -/* font stuff */ -h2 { - -webkit-font-feature-settings: "c2sc"; - -moz-font-feature-settings: "c2sc"; - font-feature-settings: "c2sc"; - font-variant-caps: small-caps; -} - -table { - -webkit-font-feature-settings: "lnum"; - -moz-font-feature-settings: "lnum"; - font-feature-settings: "lnum"; - font-variant-numeric: lining-nums; -} - -/* filters */ -.blur { - filter: url('data:image/svg+xml;charset=utf-8,#filter'); - -webkit-filter: blur(4px); - filter: blur(4px); -} -.sepia { - filter: url('data:image/svg+xml;charset=utf-8,#filter'); - -webkit-filter: sepia(.8); - filter: sepia(.8); -} - -/* pseudo-elements */ -a:before, -a:after { - content: "pseudo-elements" -} - -/* :matches() and :not() */ -p:first-child, p.specific { - color: red; -} -p:not(:first-child):not(.specific) { - background: blue; -} - -/* rgba() fallback */ -.color { - background: #99DD99; - background: rgba(153, 221, 153, 0.8); -} diff --git a/src/__tests__/fixtures/cases/example.css b/src/__tests__/fixtures/cases/example.css deleted file mode 100644 index 2bfa475..0000000 --- a/src/__tests__/fixtures/cases/example.css +++ /dev/null @@ -1,73 +0,0 @@ -/* custom properties */ -:root { - --fontSize: 1rem; - --mainColor: #12345678; - --highlightColor: hwb(190, 35%, 20%); -} - -/* custom media queries */ -@custom-media --viewport-medium (width <= 50em); - -/* some var() & calc() */ -body { - color: var(--mainColor); - - font-size: var(--fontSize); - line-height: calc(var(--fontSize) * 1.5); - padding: calc((var(--fontSize) / 2) + 1px); -} - -/* custom media query usage */ -@media (--viewport-medium) { - body { font-size: calc(var(--fontSize) * 1.2); } - /* no need for px here since browsers that supports media queries support rem already */ -} - -/* custom selectors */ -@custom-selector :--heading h1, h2, h3, h4, h5, h6; -:--heading { margin-top: 0 } - -/* colors stuff */ -a { - color: var(--highlightColor); - transition: color 1s; /* autoprefixed ! */ -} -a:hover { color: gray(255, 50%) } -a:active { color: rebeccapurple } -a:any-link { color: color(var(--highlightColor) blackness(+20%)) } - -/* font stuff */ -h2 { - font-variant-caps: small-caps; -} - -table { - font-variant-numeric: lining-nums; -} - -/* filters */ -.blur { - filter: blur(4px); -} -.sepia { - filter: sepia(.8); -} - -/* pseudo-elements */ -a::before, -a::after { - content: "pseudo-elements" -} - -/* :matches() and :not() */ -p:matches(:first-child, .specific) { - color: red; -} -p:not(:first-child, .specific) { - background: blue; -} - -/* rgba() fallback */ -.color { - background: rgba(153, 221, 153, 0.8); -} diff --git a/src/__tests__/fixtures/cases/example.expected.css b/src/__tests__/fixtures/cases/example.expected.css deleted file mode 100644 index d605897..0000000 --- a/src/__tests__/fixtures/cases/example.expected.css +++ /dev/null @@ -1,86 +0,0 @@ -/* custom properties */ - -/* custom media queries */ - -/* some var() & calc() */ -body { - color: #123456; - color: rgba(18, 52, 86, 0.47059); - - font-size: 16px; - font-size: 1rem; - line-height: 24px; - line-height: 1.5rem; - padding: calc(0.5rem + 1px); -} - -/* custom media query usage */ -@media (max-width: 50em) { - body { font-size: 1.2rem; } - /* no need for px here since browsers that supports media queries support rem already */ -} - -/* custom selectors */ -h1, -h2, -h3, -h4, -h5, -h6 { margin-top: 0 } - -/* colors stuff */ -a { - color: rgb(89, 185, 204); - -webkit-transition: color 1s; - transition: color 1s; /* autoprefixed ! */ -} -a:hover { color: #FFFFFF; color: rgba(255, 255, 255, 0.5) } -a:active { color: rgb(102, 51, 153) } -a:link,a:visited { color: rgb(89, 142, 153) } - -/* font stuff */ -h2 { - -webkit-font-feature-settings: "c2sc"; - -moz-font-feature-settings: "c2sc"; - font-feature-settings: "c2sc"; - font-variant-caps: small-caps; -} - -table { - -webkit-font-feature-settings: "lnum"; - -moz-font-feature-settings: "lnum"; - font-feature-settings: "lnum"; - font-variant-numeric: lining-nums; -} - -/* filters */ -.blur { - filter: url('data:image/svg+xml;charset=utf-8,#filter'); - -webkit-filter: blur(4px); - filter: blur(4px); -} -.sepia { - filter: url('data:image/svg+xml;charset=utf-8,#filter'); - -webkit-filter: sepia(.8); - filter: sepia(.8); -} - -/* pseudo-elements */ -a:before, -a:after { - content: "pseudo-elements" -} - -/* :matches() and :not() */ -p:first-child, p.specific { - color: red; -} -p:not(:first-child):not(.specific) { - background: blue; -} - -/* rgba() fallback */ -.color { - background: #99DD99; - background: rgba(153, 221, 153, 0.8); -} diff --git a/src/__tests__/fixtures/cases/plugin-options.css b/src/__tests__/fixtures/cases/plugin-options.css deleted file mode 100644 index b986d27..0000000 --- a/src/__tests__/fixtures/cases/plugin-options.css +++ /dev/null @@ -1,7 +0,0 @@ -:root { - --prop: value; -} - -selector { - thing: var(--prop); -} diff --git a/src/__tests__/fixtures/cases/plugin-options.expected.css b/src/__tests__/fixtures/cases/plugin-options.expected.css deleted file mode 100644 index 4883470..0000000 --- a/src/__tests__/fixtures/cases/plugin-options.expected.css +++ /dev/null @@ -1,8 +0,0 @@ -:root { - --prop: value; -} - -selector { - thing: value; - thing: var(--prop); -} diff --git a/src/__tests__/fixtures/cli.css b/src/__tests__/fixtures/cli.css deleted file mode 100755 index 6c30a4d..0000000 --- a/src/__tests__/fixtures/cli.css +++ /dev/null @@ -1,8 +0,0 @@ -:root { - --red: #e00; -} - -body { - color: var(--red); - background: url(url); -} diff --git a/src/__tests__/fixtures/cli.error.css b/src/__tests__/fixtures/cli.error.css deleted file mode 100644 index 8b52202..0000000 --- a/src/__tests__/fixtures/cli.error.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - color: var( -} diff --git a/src/__tests__/fixtures/cli.expected.css b/src/__tests__/fixtures/cli.expected.css deleted file mode 100755 index 09fcc0b..0000000 --- a/src/__tests__/fixtures/cli.expected.css +++ /dev/null @@ -1,4 +0,0 @@ -body { - color: #e00; - background: url(url); -} diff --git a/src/__tests__/fixtures/cli.watch-import-import.css b/src/__tests__/fixtures/cli.watch-import-import.css deleted file mode 100644 index 4fa557f..0000000 --- a/src/__tests__/fixtures/cli.watch-import-import.css +++ /dev/null @@ -1 +0,0 @@ -watch{} diff --git a/src/__tests__/fixtures/cli.watch-import-import2.css b/src/__tests__/fixtures/cli.watch-import-import2.css deleted file mode 100644 index 1260e2b..0000000 --- a/src/__tests__/fixtures/cli.watch-import-import2.css +++ /dev/null @@ -1 +0,0 @@ -er{} diff --git a/src/__tests__/fixtures/cli.watch-import.css b/src/__tests__/fixtures/cli.watch-import.css deleted file mode 100644 index 7068cde..0000000 --- a/src/__tests__/fixtures/cli.watch-import.css +++ /dev/null @@ -1 +0,0 @@ -/**/ \ No newline at end of file diff --git a/src/__tests__/fixtures/compress.css b/src/__tests__/fixtures/compress.css deleted file mode 100755 index f47052b..0000000 --- a/src/__tests__/fixtures/compress.css +++ /dev/null @@ -1,5 +0,0 @@ - -/*! sha */ -body { - color : black; -} diff --git a/src/__tests__/fixtures/compress.default.expected.css b/src/__tests__/fixtures/compress.default.expected.css deleted file mode 100644 index c2c6e41..0000000 --- a/src/__tests__/fixtures/compress.default.expected.css +++ /dev/null @@ -1 +0,0 @@ -/*! sha */body{color:#000} diff --git a/src/__tests__/fixtures/compress.options.expected.css b/src/__tests__/fixtures/compress.options.expected.css deleted file mode 100644 index c7e7472..0000000 --- a/src/__tests__/fixtures/compress.options.expected.css +++ /dev/null @@ -1 +0,0 @@ -/*! sha */body{color:black} diff --git a/src/__tests__/fixtures/config.css b/src/__tests__/fixtures/config.css deleted file mode 100644 index 0badc1a..0000000 --- a/src/__tests__/fixtures/config.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - color: var(--color) -} diff --git a/src/__tests__/fixtures/config.expected.css b/src/__tests__/fixtures/config.expected.css deleted file mode 100644 index 03903cc..0000000 --- a/src/__tests__/fixtures/config.expected.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - color: #e00 -} diff --git a/src/__tests__/fixtures/config.json b/src/__tests__/fixtures/config.json deleted file mode 100644 index d0aa524..0000000 --- a/src/__tests__/fixtures/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "features": { - "customProperties": { - "variables": { - "--color": "#e00" - } - } - } -} diff --git a/src/__tests__/fixtures/features/autoprefixer.css b/src/__tests__/fixtures/features/autoprefixer.css deleted file mode 100755 index 4954ce0..0000000 --- a/src/__tests__/fixtures/features/autoprefixer.css +++ /dev/null @@ -1,8 +0,0 @@ -* { - transition: transform 1s; -} - -@keyframes spin { - 0% { transform: rotate(0deg) } - 100% { transform: rotate(360deg) } -} diff --git a/src/__tests__/fixtures/features/autoprefixer.expected.css b/src/__tests__/fixtures/features/autoprefixer.expected.css deleted file mode 100755 index 175ed52..0000000 --- a/src/__tests__/fixtures/features/autoprefixer.expected.css +++ /dev/null @@ -1,14 +0,0 @@ -* { - -webkit-transition: -webkit-transform 1s; - transition: transform 1s; -} - -@-webkit-keyframes spin { - 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg) } - 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg) } -} - -@keyframes spin { - 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg) } - 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg) } -} diff --git a/src/__tests__/fixtures/features/calc.css b/src/__tests__/fixtures/features/calc.css deleted file mode 100755 index 3fe0415..0000000 --- a/src/__tests__/fixtures/features/calc.css +++ /dev/null @@ -1,3 +0,0 @@ -html { - font-size: calc(1em * 2) -} diff --git a/src/__tests__/fixtures/features/calc.expected.css b/src/__tests__/fixtures/features/calc.expected.css deleted file mode 100755 index b7a57f1..0000000 --- a/src/__tests__/fixtures/features/calc.expected.css +++ /dev/null @@ -1,3 +0,0 @@ -html { - font-size: 2em -} diff --git a/src/__tests__/fixtures/features/color-function.css b/src/__tests__/fixtures/features/color-function.css deleted file mode 100755 index 380f915..0000000 --- a/src/__tests__/fixtures/features/color-function.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: color(rgb(102, 51, 153) a(90%)) -} diff --git a/src/__tests__/fixtures/features/color-function.expected.css b/src/__tests__/fixtures/features/color-function.expected.css deleted file mode 100755 index b189789..0000000 --- a/src/__tests__/fixtures/features/color-function.expected.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: rgba(102, 51, 153, 0.9) -} diff --git a/src/__tests__/fixtures/features/color-gray.css b/src/__tests__/fixtures/features/color-gray.css deleted file mode 100644 index 5e7b691..0000000 --- a/src/__tests__/fixtures/features/color-gray.css +++ /dev/null @@ -1,3 +0,0 @@ -.bar { - color: gray(255, 50%); -} diff --git a/src/__tests__/fixtures/features/color-gray.expected.css b/src/__tests__/fixtures/features/color-gray.expected.css deleted file mode 100644 index 94281e7..0000000 --- a/src/__tests__/fixtures/features/color-gray.expected.css +++ /dev/null @@ -1,3 +0,0 @@ -.bar { - color: rgba(255, 255, 255, 0.5); -} diff --git a/src/__tests__/fixtures/features/color-hex-alpha.css b/src/__tests__/fixtures/features/color-hex-alpha.css deleted file mode 100755 index 9c3dd4d..0000000 --- a/src/__tests__/fixtures/features/color-hex-alpha.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: #9d9c -} diff --git a/src/__tests__/fixtures/features/color-hex-alpha.expected.css b/src/__tests__/fixtures/features/color-hex-alpha.expected.css deleted file mode 100755 index 3a2605a..0000000 --- a/src/__tests__/fixtures/features/color-hex-alpha.expected.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: rgba(153, 221, 153, 0.8) -} diff --git a/src/__tests__/fixtures/features/color-hwb.css b/src/__tests__/fixtures/features/color-hwb.css deleted file mode 100644 index 5019bc0..0000000 --- a/src/__tests__/fixtures/features/color-hwb.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: hwb(0, 20%, 40%) -} diff --git a/src/__tests__/fixtures/features/color-hwb.expected.css b/src/__tests__/fixtures/features/color-hwb.expected.css deleted file mode 100755 index 9cc2d1f..0000000 --- a/src/__tests__/fixtures/features/color-hwb.expected.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: rgb(153, 51, 51) -} diff --git a/src/__tests__/fixtures/features/color-rebeccapurple.css b/src/__tests__/fixtures/features/color-rebeccapurple.css deleted file mode 100755 index 33dc9bb..0000000 --- a/src/__tests__/fixtures/features/color-rebeccapurple.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: rebeccapurple -} diff --git a/src/__tests__/fixtures/features/color-rebeccapurple.expected.css b/src/__tests__/fixtures/features/color-rebeccapurple.expected.css deleted file mode 100755 index 17739fc..0000000 --- a/src/__tests__/fixtures/features/color-rebeccapurple.expected.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: rgb(102, 51, 153) -} diff --git a/src/__tests__/fixtures/features/color-rgba.css b/src/__tests__/fixtures/features/color-rgba.css deleted file mode 100644 index 42d8d13..0000000 --- a/src/__tests__/fixtures/features/color-rgba.css +++ /dev/null @@ -1,4 +0,0 @@ -.foo { - background: rgba(153, 221, 153, 0.8); - border: solid 1px rgba(100,102,103,.3); -} diff --git a/src/__tests__/fixtures/features/color-rgba.expected.css b/src/__tests__/fixtures/features/color-rgba.expected.css deleted file mode 100644 index 013f935..0000000 --- a/src/__tests__/fixtures/features/color-rgba.expected.css +++ /dev/null @@ -1,6 +0,0 @@ -.foo { - background: #99DD99; - background: rgba(153, 221, 153, 0.8); - border: solid 1px #646667; - border: solid 1px rgba(100,102,103,.3); -} diff --git a/src/__tests__/fixtures/features/custom-media.css b/src/__tests__/fixtures/features/custom-media.css deleted file mode 100755 index bacd858..0000000 --- a/src/__tests__/fixtures/features/custom-media.css +++ /dev/null @@ -1,5 +0,0 @@ -@custom-media --small-viewport (max-width: 30em); - -@media (--small-viewport) { - /* styles for small viewport */ -} diff --git a/src/__tests__/fixtures/features/custom-media.expected.css b/src/__tests__/fixtures/features/custom-media.expected.css deleted file mode 100755 index ee9d211..0000000 --- a/src/__tests__/fixtures/features/custom-media.expected.css +++ /dev/null @@ -1,5 +0,0 @@ - - -@media (max-width: 30em) { - /* styles for small viewport */ -} diff --git a/src/__tests__/fixtures/features/custom-properties.css b/src/__tests__/fixtures/features/custom-properties.css deleted file mode 100755 index 65c688e..0000000 --- a/src/__tests__/fixtures/features/custom-properties.css +++ /dev/null @@ -1,7 +0,0 @@ -:root { - --color: #e00 -} - -body { - color: var(--color) -} diff --git a/src/__tests__/fixtures/features/custom-properties.expected.css b/src/__tests__/fixtures/features/custom-properties.expected.css deleted file mode 100755 index 18ddf03..0000000 --- a/src/__tests__/fixtures/features/custom-properties.expected.css +++ /dev/null @@ -1,5 +0,0 @@ - - -body { - color: #e00 -} diff --git a/src/__tests__/fixtures/features/custom-selectors.css b/src/__tests__/fixtures/features/custom-selectors.css deleted file mode 100644 index b7e7a40..0000000 --- a/src/__tests__/fixtures/features/custom-selectors.css +++ /dev/null @@ -1,5 +0,0 @@ -@custom-selector :--heading h1, h2, h3, h4, h5, h6; - -article :--heading + p{ - margin-top: 0; -} diff --git a/src/__tests__/fixtures/features/custom-selectors.expected.css b/src/__tests__/fixtures/features/custom-selectors.expected.css deleted file mode 100644 index fdac390..0000000 --- a/src/__tests__/fixtures/features/custom-selectors.expected.css +++ /dev/null @@ -1,8 +0,0 @@ -article h1 + p, -article h2 + p, -article h3 + p, -article h4 + p, -article h5 + p, -article h6 + p{ - margin-top: 0; -} diff --git a/src/__tests__/fixtures/features/filter.css b/src/__tests__/fixtures/features/filter.css deleted file mode 100644 index d7fa2b7..0000000 --- a/src/__tests__/fixtures/features/filter.css +++ /dev/null @@ -1,3 +0,0 @@ -.blur { - filter: blur(4px); -} diff --git a/src/__tests__/fixtures/features/filter.expected.css b/src/__tests__/fixtures/features/filter.expected.css deleted file mode 100644 index c4d1b58..0000000 --- a/src/__tests__/fixtures/features/filter.expected.css +++ /dev/null @@ -1,4 +0,0 @@ -.blur { - filter: url('data:image/svg+xml;charset=utf-8,#filter'); - filter: blur(4px); -} diff --git a/src/__tests__/fixtures/features/font-variant.css b/src/__tests__/fixtures/features/font-variant.css deleted file mode 100644 index d561bf1..0000000 --- a/src/__tests__/fixtures/features/font-variant.css +++ /dev/null @@ -1,7 +0,0 @@ -h2 { - font-variant-caps: small-caps; -} - -table { - font-variant-numeric: lining-nums; -} diff --git a/src/__tests__/fixtures/features/font-variant.expected.css b/src/__tests__/fixtures/features/font-variant.expected.css deleted file mode 100644 index 2e13f35..0000000 --- a/src/__tests__/fixtures/features/font-variant.expected.css +++ /dev/null @@ -1,9 +0,0 @@ -h2 { - font-feature-settings: "c2sc"; - font-variant-caps: small-caps; -} - -table { - font-feature-settings: "lnum"; - font-variant-numeric: lining-nums; -} diff --git a/src/__tests__/fixtures/features/media-queries-range.css b/src/__tests__/fixtures/features/media-queries-range.css deleted file mode 100644 index e87927a..0000000 --- a/src/__tests__/fixtures/features/media-queries-range.css +++ /dev/null @@ -1,2 +0,0 @@ -@media screen and (width >= 500px) and (width <= 1200px) {} -@media screen and (500px <= width <= 1200px) {} diff --git a/src/__tests__/fixtures/features/media-queries-range.expected.css b/src/__tests__/fixtures/features/media-queries-range.expected.css deleted file mode 100644 index bf82f6f..0000000 --- a/src/__tests__/fixtures/features/media-queries-range.expected.css +++ /dev/null @@ -1,2 +0,0 @@ -@media screen and (min-width: 500px) and (max-width: 1200px) {} -@media screen and (min-width: 500px) and (max-width: 1200px) {} diff --git a/src/__tests__/fixtures/features/pseudo-class-any-link.css b/src/__tests__/fixtures/features/pseudo-class-any-link.css deleted file mode 100644 index 7cc79d6..0000000 --- a/src/__tests__/fixtures/features/pseudo-class-any-link.css +++ /dev/null @@ -1,3 +0,0 @@ -nav :any-link > span { - background-color: yellow; -} diff --git a/src/__tests__/fixtures/features/pseudo-class-any-link.expected.css b/src/__tests__/fixtures/features/pseudo-class-any-link.expected.css deleted file mode 100644 index 4485199..0000000 --- a/src/__tests__/fixtures/features/pseudo-class-any-link.expected.css +++ /dev/null @@ -1,3 +0,0 @@ -nav :link > span,nav :visited > span { - background-color: yellow; -} diff --git a/src/__tests__/fixtures/features/pseudo-class-matches.css b/src/__tests__/fixtures/features/pseudo-class-matches.css deleted file mode 100644 index ebfa974..0000000 --- a/src/__tests__/fixtures/features/pseudo-class-matches.css +++ /dev/null @@ -1,3 +0,0 @@ -p:matches(:first-child, .specific) { - color: red; -} diff --git a/src/__tests__/fixtures/features/pseudo-class-matches.expected.css b/src/__tests__/fixtures/features/pseudo-class-matches.expected.css deleted file mode 100644 index 7dba525..0000000 --- a/src/__tests__/fixtures/features/pseudo-class-matches.expected.css +++ /dev/null @@ -1,3 +0,0 @@ -p:first-child, p.specific { - color: red; -} diff --git a/src/__tests__/fixtures/features/pseudo-class-not.css b/src/__tests__/fixtures/features/pseudo-class-not.css deleted file mode 100644 index b770fd4..0000000 --- a/src/__tests__/fixtures/features/pseudo-class-not.css +++ /dev/null @@ -1,3 +0,0 @@ -p:not(:first-child, .specific) { - background: blue; -} diff --git a/src/__tests__/fixtures/features/pseudo-class-not.expected.css b/src/__tests__/fixtures/features/pseudo-class-not.expected.css deleted file mode 100644 index 0a99017..0000000 --- a/src/__tests__/fixtures/features/pseudo-class-not.expected.css +++ /dev/null @@ -1,3 +0,0 @@ -p:not(:first-child):not(.specific) { - background: blue; -} diff --git a/src/__tests__/fixtures/features/pseudo-elements.css b/src/__tests__/fixtures/features/pseudo-elements.css deleted file mode 100644 index e924841..0000000 --- a/src/__tests__/fixtures/features/pseudo-elements.css +++ /dev/null @@ -1,6 +0,0 @@ -.foo::after { - content:"pseudoelement" -} -.foo::before { - content:"pseudoelement" -} diff --git a/src/__tests__/fixtures/features/pseudo-elements.expected.css b/src/__tests__/fixtures/features/pseudo-elements.expected.css deleted file mode 100644 index aa56a6b..0000000 --- a/src/__tests__/fixtures/features/pseudo-elements.expected.css +++ /dev/null @@ -1,6 +0,0 @@ -.foo:after { - content:"pseudoelement" -} -.foo:before { - content:"pseudoelement" -} diff --git a/src/__tests__/fixtures/features/rem.css b/src/__tests__/fixtures/features/rem.css deleted file mode 100644 index dcddbf3..0000000 --- a/src/__tests__/fixtures/features/rem.css +++ /dev/null @@ -1,11 +0,0 @@ -.sky { - margin: 2.5rem 2px 3em 100%; - color: blue; -} - -@media screen and (min-width: 20rem) { - .leaf { - margin-bottom: 1.333rem; - font-size: 1.5rem; - } -} \ No newline at end of file diff --git a/src/__tests__/fixtures/features/rem.expected.css b/src/__tests__/fixtures/features/rem.expected.css deleted file mode 100644 index b18fb60..0000000 --- a/src/__tests__/fixtures/features/rem.expected.css +++ /dev/null @@ -1,12 +0,0 @@ -.sky { - margin: 40px 2px 3em 100%; - margin: 2.5rem 2px 3em 100%; - color: blue; -} - -@media screen and (min-width: 20rem) { - .leaf { - margin-bottom: 1.333rem; - font-size: 1.5rem; - } -} \ No newline at end of file diff --git a/src/__tests__/fixtures/import.css b/src/__tests__/fixtures/import.css deleted file mode 100755 index 24bd542..0000000 --- a/src/__tests__/fixtures/import.css +++ /dev/null @@ -1,5 +0,0 @@ -@import "./import.imported.css"; - -html { - background: #eee; -} diff --git a/src/__tests__/fixtures/import.default.expected.css b/src/__tests__/fixtures/import.default.expected.css deleted file mode 100755 index e64c573..0000000 --- a/src/__tests__/fixtures/import.default.expected.css +++ /dev/null @@ -1,7 +0,0 @@ -html { - color: #111; -} - -html { - background: #eee; -} diff --git a/src/__tests__/fixtures/import.imported.css b/src/__tests__/fixtures/import.imported.css deleted file mode 100755 index 8647ee6..0000000 --- a/src/__tests__/fixtures/import.imported.css +++ /dev/null @@ -1,3 +0,0 @@ -html { - color: #111; -} diff --git a/src/__tests__/fixtures/import.options.expected.css b/src/__tests__/fixtures/import.options.expected.css deleted file mode 100755 index 1237158..0000000 --- a/src/__tests__/fixtures/import.options.expected.css +++ /dev/null @@ -1,9 +0,0 @@ -html { - color: #111; -} - - new {} - -html { - background: #eee; -} diff --git a/src/__tests__/fixtures/sourcemap.css b/src/__tests__/fixtures/sourcemap.css deleted file mode 100644 index 0bb9036..0000000 --- a/src/__tests__/fixtures/sourcemap.css +++ /dev/null @@ -1,5 +0,0 @@ -@import "sourcemap.imported.css"; - -body { - color: red; -} diff --git a/src/__tests__/fixtures/sourcemap.expected-start b/src/__tests__/fixtures/sourcemap.expected-start deleted file mode 100644 index 0a9cbb7..0000000 --- a/src/__tests__/fixtures/sourcemap.expected-start +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["src/__tests__/fixtures/sourcemap.imported.css","src/__tests__/fixtures/sourcemap.css"],"names":[],"mappings": diff --git a/src/__tests__/fixtures/sourcemap.expected.css b/src/__tests__/fixtures/sourcemap.expected.css deleted file mode 100755 index 4012ebc..0000000 --- a/src/__tests__/fixtures/sourcemap.expected.css +++ /dev/null @@ -1,9 +0,0 @@ -html { - background: blue; -} - -body { - color: red; -} - -/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvZml4dHVyZXMvc291cmNlbWFwLmltcG9ydGVkLmNzcyIsInRlc3QvZml4dHVyZXMvc291cmNlbWFwLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGlCQUFpQjtDQUNsQjs7QUNBRDtFQUNFLFdBQVc7Q0FDWiIsImZpbGUiOiJ0ZXN0L2ZpeHR1cmVzL3NvdXJjZW1hcC5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyJodG1sIHtcbiAgYmFja2dyb3VuZDogYmx1ZTtcbn1cbiIsIkBpbXBvcnQgXCJzb3VyY2VtYXAuaW1wb3J0ZWQuY3NzXCI7XG5cbmJvZHkge1xuICBjb2xvcjogcmVkO1xufVxuIl19 */ diff --git a/src/__tests__/fixtures/sourcemap.imported.css b/src/__tests__/fixtures/sourcemap.imported.css deleted file mode 100755 index c913323..0000000 --- a/src/__tests__/fixtures/sourcemap.imported.css +++ /dev/null @@ -1,3 +0,0 @@ -html { - background: blue; -} diff --git a/src/__tests__/fixtures/url.css b/src/__tests__/fixtures/url.css deleted file mode 100644 index 78fcc05..0000000 --- a/src/__tests__/fixtures/url.css +++ /dev/null @@ -1 +0,0 @@ -@import 'url/dep.css' diff --git a/src/__tests__/fixtures/url.default.expected.css b/src/__tests__/fixtures/url.default.expected.css deleted file mode 100644 index 13cb09a..0000000 --- a/src/__tests__/fixtures/url.default.expected.css +++ /dev/null @@ -1,6 +0,0 @@ -@font-face { - src: url('url/assets/font.woff?v3#dontcare') -} -body { - background: url('url/assets/pixel.gif') -} diff --git a/src/__tests__/fixtures/url.options.expected.css b/src/__tests__/fixtures/url.options.expected.css deleted file mode 100644 index 0605c5a..0000000 --- a/src/__tests__/fixtures/url.options.expected.css +++ /dev/null @@ -1,6 +0,0 @@ -@font-face { - src: url('./assets/font.woff?v3#dontcare') -} -body { - background: url('data:image/gif;base64,R0lGODlhAQABAJH/AP///wAAAP///wAAACH/C0FET0JFOklSMS4wAt7tACH5BAEAAAIALAAAAAABAAEAAAICVAEAOw==') -} diff --git a/src/__tests__/fixtures/url/assets/font.woff b/src/__tests__/fixtures/url/assets/font.woff deleted file mode 100644 index 34fdfde24860b4170aa4d1015ca47021dc89ab2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19616 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 S_ydk5nhF2_0a7dP4FCXcq^%MF diff --git a/src/__tests__/fixtures/url/assets/pixel.gif b/src/__tests__/fixtures/url/assets/pixel.gif deleted file mode 100644 index 46a2cf086ca4829b2afacec093d4562ec6c16f59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67 zcmZ?wbhEHbWMp7unE0RJ|Ns9C3{X<>KewZczmuz#XON+u0n@#=42nNl7#SFt7<7PY Nfa*bPrVvI3YXHjL5YGSr diff --git a/src/__tests__/fixtures/url/dep.css b/src/__tests__/fixtures/url/dep.css deleted file mode 100644 index e9081db..0000000 --- a/src/__tests__/fixtures/url/dep.css +++ /dev/null @@ -1,6 +0,0 @@ -@font-face { - src: url('./assets/font.woff?v3#dontcare') -} -body { - background: url('./assets/pixel.gif') -} diff --git a/src/__tests__/index.js b/src/__tests__/index.js new file mode 100644 index 0000000..d2b8a4c --- /dev/null +++ b/src/__tests__/index.js @@ -0,0 +1,12 @@ +import tape from "tape" + +import postcssnext from ".." + +tape("postcss-cssnext is a postcss plugin", (t) => { + t.ok( + typeof postcssnext.process === "function", + "should have the postcss process() function available" + ) + + t.end() +}) diff --git a/src/__tests__/messages/index.js b/src/__tests__/messages/index.js deleted file mode 100644 index a9126bf..0000000 --- a/src/__tests__/messages/index.js +++ /dev/null @@ -1,45 +0,0 @@ -import fs from "fs" -import path from "path" - -import opn from "opn" - -import cssnext from "../.." - -console.log("# cssnext renderering test for messages styles") - -const msg = "This is a test message" -const page = path.join("dist", "__tests__styles.html") - -const css = cssnext( - ` -@import url(http://) -:root { - --var: test; -} -@custom-selector --h h1, h2; -body { - color: var(--test); -} - `, - { - plugins: [ - (styles, result) => { - result.warn(msg) - }, - ], - messages: { - browser: true, - }, - } -) - -fs.writeFileSync( - page, - ` -cssnext message rendering test -`, -) - -opn(page) diff --git a/src/__tests__/option.browsers.js b/src/__tests__/option.browsers.js deleted file mode 100644 index 5d6e98a..0000000 --- a/src/__tests__/option.browsers.js +++ /dev/null @@ -1,65 +0,0 @@ -const test = require("tape") - -const cssnext = require("..") - -test("cssnext browsers option", function(t) { - - // no recent browser need pixrem - const remInput = "body{font-size:2rem}" - t.equal( - cssnext( - remInput, - {browsers: "last 1 version"} - ), - remInput, - "should not enable px fallback when all browsers support it" - ) - - const customPropsInput = ":root{--foo:bar}baz{qux:var(--foo)}" - const customPropsOutput = "baz{qux: bar}" - - // fx 30 doesn't handle custom prop - t.equal( - cssnext(customPropsInput, {browsers: "Firefox >= 30"}), - customPropsOutput, - "should enable custom properties when browsers do not support it" - ) - - // fx 31 handle custom prop - t.equal( - cssnext(customPropsInput, {browsers: "Firefox >= 31"}), - customPropsInput, - "should NOT enable custom properties when browsers support it" - ) - - // fx 31 support but not IE 8 - t.equal( - cssnext(customPropsInput, {browsers: "Firefox >= 31, IE 8"}), - customPropsOutput, - "should enable custom properties when at least one browsers do not " + - "support it" - ) - - t.end() -}) - -test("cssnext browsers option propagation", function(t) { - const input = "body{transition: 1s}" - const output = "body{-webkit-transition: 1s;transition: 1s}" - - // Safari 6 need -webkit prefix - t.equal( - cssnext(input, {browsers: "Safari 6"}), - output, - "should propagate browsers option to autoprefixer" - ) - - // Safari 6.1 do not need -webkit prefix - t.equal( - cssnext(input, {browsers: "Safari 6.1"}), - input, - "should propagate browsers option to autoprefixer" - ) - - t.end() -}) diff --git a/src/__tests__/option.compress.js b/src/__tests__/option.compress.js deleted file mode 100644 index f86ec36..0000000 --- a/src/__tests__/option.compress.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Test dependencies - */ -const test = require("tape") - -const utils = require("./utils") -const cssnext = require("..") -const postcss = require("postcss") - -test("cssnext compress option", function(t) { - const input = utils.readFixture("compress") - const expected = { - default: utils.readFixture("compress.default.expected").trim(), - options: utils.readFixture("compress.options.expected").trim(), - } - - t.equal( - cssnext( - input, - { - compress: true, - } - ).trim(), - expected.default, - "should be able to compress" - ) - t.equal( - cssnext( - input, - { - compress: { - colormin: false, - }, - } - ).trim(), - expected.options, - "should be able to compress with options" - ) - t.equal( - postcss().use( - cssnext({ - compress: true, - }) - ).process(input).css.trim(), - expected.default, - "should be able to compress even as a postcss plugin" - ) - - t.end() -}) diff --git a/src/__tests__/option.features.js b/src/__tests__/option.features.js deleted file mode 100644 index 7f7226a..0000000 --- a/src/__tests__/option.features.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Test dependencies - */ -const test = require("tape") - -const utils = require("./utils") -const cssnext = require("..") -const cssnextStandalone = require("../cssnext") - -/** - * Features tests - */ -const toSlug = require("to-slug-case") -const testFeature = function( - t, - feature, - cssnextInstance, - version, - source, - input, - expected -) { - const options = {from: source, sourcemap: false, features: {}} - - // disable all features - Object.keys(cssnextInstance.features).forEach(function(key) { - options.features[key] = false - }) - - const css = cssnextInstance(input, options) - t.notEqual( - css, - expected, - version + ": should not add " + feature + " support if disabled" - ) - t.equal( - css, - input, - version + ": should not modify input if " + feature + " is disabled" - ) - - // enable only the one we want to test... - options.features[feature] = true - - // ...except "url" because we want to validate its behaviour when integrated - // with "import" - if (feature === "url") { - options.features.import = true - } - t.equal( - cssnextInstance(input, options).trim(), - expected.trim(), - version + ": should add " + feature + " support" - ) -} - -Object.keys(cssnext.features).forEach(function(name) { - const slug = toSlug(name) - const source = utils.fixturePath("features/" + slug) - const input = utils.readFixture("features/" + slug) - const expected = utils.readFixture("features/" + slug + ".expected") - - test(slug, function(t) { - testFeature(t, name, cssnext, "node.js", source, input, expected) - - // we do not support @import or url rewriting in the browser - if (name === "import" || name === "url") { - t.end() - return - } - - testFeature(t, name, cssnextStandalone, "browser", source, input, expected) - - t.end() - }) -}) diff --git a/src/__tests__/option.import.js b/src/__tests__/option.import.js deleted file mode 100644 index f0ea2ad..0000000 --- a/src/__tests__/option.import.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Test dependencies - */ -const test = require("tape") - -const utils = require("./utils") -const cssnext = require("..") -const postcss = require("postcss") - -test("cssnext import option", function(t) { - const input = utils.readFixture("import") - const expected = { - default: utils.readFixture("import.default.expected").trim(), - options: utils.readFixture("import.options.expected").trim(), - } - const opts = {from: "src/__tests__/fixtures/here"} - function transformFn(c) { - return c + "\n new {}" - } - t.equal( - cssnext(input, opts).trim(), - expected.default, - "should be able to import" - ) - t.equal( - cssnext(input, { - from: opts.from, - import: { - transform: transformFn, - }, - }).trim(), - expected.options, - "should be able to import with options" - ) - t.equal( - postcss().use(cssnext()).process(input, opts).css.trim(), - expected.default, - "should be able to import even as a postcss plugin" - ) - const importOpt = { - transform: transformFn, - } - Object.freeze(importOpt) - t.doesNotThrow(function() { - cssnext(input, { - from: opts.from, - import: importOpt, - }).trim() - }, - expected.options, - "should not use original object as option" - ) - t.end() -}) diff --git a/src/__tests__/option.messages.js b/src/__tests__/option.messages.js deleted file mode 100644 index 6170c0e..0000000 --- a/src/__tests__/option.messages.js +++ /dev/null @@ -1,84 +0,0 @@ -import test from "tape" - -import cssnext from ".." - -test("cssnext option: messages", (t) => { - - const msg = "This is a message" - const defaultOptions = { - plugins: [ - (styles, result) => { - result.warn(msg) - }, - ], - messages: true, - } - - t.equal( - cssnext({ - ...defaultOptions, - messages: false, - }) - .process("test{}") - .warnings()[0].text, - msg, - "should pass messages if messages option is off" - ) - - t.ok( - cssnext({ - ...defaultOptions, - messages: { - browser: true, - }, - }) - .process("test{}") - .css - .indexOf(`${ msg }`) > -1 - , - "should add messages in css" - ) - - t.ok( - cssnext({ - ...defaultOptions, - messages: { - browser: false, - }, - }) - .process("test{}") - .css - .indexOf(`content: "${ msg }"`) === -1 - , - "should not add messages in css if key is === false" - ) - - t.ok( - cssnext({ - ...defaultOptions, - messages: {}, - }) - .process("test{}") - .css - .indexOf(`content: "${ msg }"`) === -1 - , - "should not add messages in css if key is not present" - ) - - // we should do the same for "console" value, but we need to test stdout - // and I am lazy atm. Finger crossed. - // t.ok( - // cssnext({ - // ...defaultOptions, - // messages: { - // console: true, - // }, - // }) - // .process("test{}") - // .css - // , - // "should show messages in the console" - // ) - - t.end() -}) diff --git a/src/__tests__/option.plugins.js b/src/__tests__/option.plugins.js deleted file mode 100644 index 6409b6c..0000000 --- a/src/__tests__/option.plugins.js +++ /dev/null @@ -1,25 +0,0 @@ -import test from "tape" - -import cssnext from ".." - -test("cssnext option: plugins", (t) => { - - t.equal( - cssnext( - ":root{} @notOk", - { - plugins: [ - styles => { - styles.eachAtRule(atRule => { - atRule.name = "ok" - }) - }, - ], - } - ), - "@ok", - "should allow to add custom plugins" - ) - - t.end() -}) diff --git a/src/__tests__/option.sourcemap.js b/src/__tests__/option.sourcemap.js deleted file mode 100644 index 9cc256c..0000000 --- a/src/__tests__/option.sourcemap.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Test dependencies - */ -const test = require("tape") - -const utils = require("./utils") -const cssnext = require("..") - -/** - * Sourcemap tests - */ -test("sourcemap", function(t) { - const options = { - from: "./src/__tests__/fixtures/sourcemap.css", - sourcemap: true, - } - t.ok( - cssnext( - utils.readFixture("sourcemap"), - options - ) - .indexOf("/*# sourceMappingURL=data:application/json;base64,") - > -1, - "should contain a correct inlined sourcemap" - ) - - const result = cssnext( - utils.readFixture("sourcemap"), - { - from: "./src/__tests__/fixtures/sourcemap.css", - map: {inline: false}, - } - ) - - t.ok( - /* eslint-disable max-len */ - result.map.toString() - .indexOf(utils.readFixture("sourcemap.expected-start", "").trim()) - > -1 - , - /* eslint-enable max-len */ - "should contain a correct sourcemap" - ) - - t.end() -}) diff --git a/src/__tests__/option.url.js b/src/__tests__/option.url.js deleted file mode 100644 index c65d39c..0000000 --- a/src/__tests__/option.url.js +++ /dev/null @@ -1,32 +0,0 @@ -const test = require("tape") - -const utils = require("./utils") -const cssnext = require("..") -const postcss = require("postcss") - -test("cssnext url option", function(t) { - const input = utils.readFixture("url") - const expected = { - default: utils.readFixture("url.default.expected").trim(), - options: utils.readFixture("url.options.expected").trim(), - } - const opts = {from: "./src/__tests__/fixtures/url.css"} - - t.equal( - cssnext(input, opts).trim(), - expected.default, - "should be able to adjust url" - ) - t.equal( - cssnext(input, {...opts, url: {url: "inline"}}).trim(), - expected.options, - "should be able to adjust url with options" - ) - t.equal( - postcss().use(cssnext(opts)).process(input, opts).css.trim(), - expected.default, - "should be able to adjust url even as a postcss plugin" - ) - - t.end() -}) diff --git a/src/__tests__/prevent-webpack-usage.js b/src/__tests__/prevent-webpack-usage.js deleted file mode 100644 index 5d39910..0000000 --- a/src/__tests__/prevent-webpack-usage.js +++ /dev/null @@ -1,51 +0,0 @@ -const test = require("tape") - -import {join as joinPath, dirname} from "path" - -import webpack from "webpack" - -test("cssnext-loader recommendation", function(t) { - webpack( - { - entry: { - "prevent-webpack-usage": [ - // we don't care about what file is being used - // because this should throw an error before the input being used - "./package.json", - ], - }, - output: { - // we don't care about the output... - path: "./dist/__tests__/", - filename: "prevent-webpack-usage.tmp-webpack-bundle.js", - }, - module: { - loaders: [ - { - test: /\.json$/, - // use directly cssnext index.js - loader: joinPath(dirname(__filename), "..", "index.js"), - }, - ], - }, - }, - (err, stats) => { - if (err) { - throw err - } - - if (!stats.hasErrors()) { - t.fail( - "doesn't throw an error if cssnext is used directly as webpack loader" - ) - } - else { - t.ok( - stats.compilation.errors[0].message.indexOf("cssnext-loader") > -1, - "should recommand cssnext-loader" - ) - } - - t.end() - }) -}) diff --git a/src/__tests__/utils/index.js b/src/__tests__/utils/index.js deleted file mode 100644 index 20ec7cf..0000000 --- a/src/__tests__/utils/index.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Module dependencies - */ -const fs = require("fs") -const cssnext = require("../..") - -/** - * Check if a string is contained into another - * - * @param {String} string string to look into - * @param {String} piece string to find - * @return {Boolean} returns true if piece is contained in string - */ -function contains(string, piece) { - return Boolean(string.indexOf(piece) + 1) -} - -/** - * get fixture path - * @param {String} name - * @param {String} ext (optional extension, default to ".css") - * @return the fixture filename -*/ -function fixturePath(name, ext) { - ext = (ext !== undefined ? ext : ".css") - return "src/__tests__/fixtures/" + name + ext -} - -/** - * Remove a fixture by `filename`. - * - * @param {String} filename - */ -function remove(filename) { - const file = fixturePath(filename) - if (!fs.existsSync(file)) { - return - } - fs.unlinkSync(file) -} - -/** - * read a fixture - * @param {String} name - * @param {String} ext (optional extension, default to ".css") - * @return the fixture content - */ -function readFixture(name, ext) { - return fs.readFileSync(fixturePath(name, ext), "utf8") -} - -/** - * compare fixtures input with expected output - * @param {Object} t tape test helper - * @param {String} name eg: "cases/color" - * @param {String} message message for tape helper - * @param {Object|Function} options cssnext options - */ -function compareFixtures(t, name, message, options) { - let actual - if (typeof options === "function") { - actual = options(readFixture(name)) - } - else { - options = options || {} - options.from = fixturePath(name) - actual = cssnext(readFixture(name), options) - } - - // handy thing: checkout actual in the *.actual.css file - fs.writeFile(fixturePath(name + ".actual"), actual) - - const expected = readFixture(name + ".expected") - - return t.equal( - actual.trim(), - expected.trim(), - message !== undefined - ? message - : "processed fixture '" + name + "' should be equal to expected output" - ) -} - -/** - * Exposes functions - * - * @type {Object} - */ -module.exports = { - contains: contains, - remove: remove, - compareFixtures: compareFixtures, - fixturePath: fixturePath, - readFixture: readFixture, -} diff --git a/src/__tests__/utils/isBabel.js b/src/__tests__/utils/isBabel.js deleted file mode 100644 index e0b5f89..0000000 --- a/src/__tests__/utils/isBabel.js +++ /dev/null @@ -1 +0,0 @@ -export default typeof _babelPolyfill !== "undefined" && _babelPolyfill === true diff --git a/src/bin.js b/src/bin.js deleted file mode 100755 index 9d8c626..0000000 --- a/src/bin.js +++ /dev/null @@ -1,224 +0,0 @@ -#!/usr/bin/env node - -import fs from "fs" -import path from "path" - -// until this land in a stable version of node (for a while) -// https://github.com/joyent/node/commit/20176a -// we will this instead of process.exit() -import exit from "exit" - -import mkdirp from "mkdirp" -import color from "chalk" -import program from "commander" - -import cssnext from ".." -import pkg from "../package" - -program - .version(pkg.version) - .usage("[options] [ []]") - .option("-C, --config ", "use the config file") - .option("-b, --browsers ", "browsers list (comma separated)") - .option("-I, --no-import", "do not inline @import") - .option("-U, --no-url", "do not adjust url()") - .option("-c, --compress", "compress output") - .option("-s, --sourcemap", "add sourcemap") - .option("-w, --watch", "watch the input file for changes") - .option("-v, --verbose", "verbose output") - -// register features as flag -const format = require("util").format -const toSlug = require("to-slug-case") -const toSpace = require("to-space-case") -Object.keys(cssnext.features).forEach(function(feature) { - const flag = format("--no-%s", toSlug(feature)) - const desc = format("disable %s support", toSpace(feature)) - program.option(flag, desc) -}) - -/* eslint-disable no-multiple-empty-lines */ -program.on("--help", function() { - console.log(function() {/* - Examples: - - # pass an input and output file - $ cssnext input.css output.css - - - # start cssnext watcher (need input & output) - $ cssnext --watch input.css output.css - - - # using stdin and stdout - $ cat input.css | cssnext > output.css - */ - }.toString().split("\n").slice(1, -2).join("\n")) -}) -/* eslint-enable no-multiple-empty-lines */ - -program.parse(process.argv) - -const config = program.config ? require(path.resolve(program.config)) : {} -if (!config.features) { - config.features = {} -} -// command line flags override config file -Object.keys(cssnext.features).forEach(function(feature) { - if (program[feature] === false) { - config.features[feature] = false - } -}) -if ("browsers" in program) { - config.browsers = program.browsers -} -if ("import" in program) { - config.import = program.import -} -if ("url" in program) { - config.url = program.url -} -if ("sourcemap" in program) { - config.sourcemap = program.sourcemap -} -if ("compress" in program) { - config.compress = program.compress -} -if ("watch" in program) { - config.watch = program.watch -} - -const input = program.args[0] ? path.resolve(program.args[0]) : null -const output = program.args[1] ? path.resolve(program.args[1]) : null -const verbose = program.verbose - -if (input && !fs.existsSync(input)) { - console.error(color.red("Unable to read file"), input) - exit(1) -} - -config.from = input -config.to = output - -if (output) { - mkdirp.sync(path.dirname(output)) -} - -// init & adjust watcher with postcss-import dependencies -let watcher -if (config.watch) { - if (!input || !output) { - console.error( - color.red("--watch option need both & files to work") - ) - exit(3) - } - - watcher = require("chokidar").watch(input, {ignoreInitial: true}) - - if (verbose) { - log(color.cyan("Watching"), input) - } - - // https://github.com/paulmillr/chokidar/issues/288 - // ready event might not be triggered at all - // watcher.on("ready", function() { - // if (verbose) { - // log(color.cyan("Watcher ready"), input) - // } - // }) - - watcher.on("change", transform) - - // watch `@import`ed files - if (config.import) { - // keep a up to date list of imported files - let importedFiles = [input] - const arrayDiff = function(array, array2) { - return array.filter(function(i) { - return array2.indexOf(i) < 0 - }) - } - - const rebaseFile = function(file) { - return path.relative(process.cwd(), file) - } - - const watcherOnImport = function(imported) { - const toUnwatch = arrayDiff(importedFiles, imported) - const toWatch = arrayDiff(imported, importedFiles) - toUnwatch.forEach(function(file) { - watcher.unwatch(rebaseFile(file)) - }) - toWatch.forEach(function(file) { - watcher.add(rebaseFile(file)) - }) - importedFiles = imported - } - - // import need an object so we can pass onImport() cb - if (typeof config.import !== "object") { - config.import = {} - } - - // keep the existing onImport callback if any - if (config.import.onImport) { - config.import.onImport = function(files) { - const originalOnImport = config.import.onImport - watcherOnImport(files) - originalOnImport(files) - } - } - // or just add the watcher updater onImport() cb - else { - config.import.onImport = watcherOnImport - } - } -} - -function transform() { - require("read-file-stdin")(input, function(err, buffer) { - if (err) { - throw err - } - - try { - const css = cssnext(buffer.toString(), config) - - require("write-file-stdout")(output, css) - if (verbose && output) { - log(color.cyan("Output written"), output) - } - } - catch (e) { - console.error() - console.error(color.bold("cssnext encounters an error:")) - console.error() - console.error(color.red(e.message)) - if (e.stack) { - console.error(e.stack.split("\n").slice(1).join("\n").grey) - console.error() - } - console.error("If this error looks like a bug, please report it here:") - console.error(color.grey("❯ ") + color.cyan(pkg.bugs.url)) - console.error() - if (!config.watch) { - exit(2) - } - } - }) -} - -transform() - -/** - * log content prefixed by time - * - * @return {String} output all given parameters prefixed by the current locale - * time - */ -function log() { - const args = [].slice.call(arguments) - args.unshift("[" + color.grey(new Date().toLocaleTimeString()) + "]") - console.log.apply(console.log, args) -} diff --git a/src/features-activation-map.js b/src/features-activation-map.js deleted file mode 100644 index afefffa..0000000 --- a/src/features-activation-map.js +++ /dev/null @@ -1,29 +0,0 @@ -// Some features might affect others (eg: var() in a calc() -// in order to prevent issue, the map contains a sort of dependencies list -// -// null == always enable (& no caniuse data) -export default { - customProperties: ["css-variables"], - // calc() transformation only make sense with transformed custom properties, - // don't you think ? - // calc: null, - // @todo open PR on caniuse repo https://github.com/Fyrd/caniuse - // customMedia: [null], - // mediaQueriesRange: [null], - // customSelectors: [null], - // colorRebeccapurple: [null], // @todo can be done easily - // colorHwb: [null], - // colorGray: [null], - // colorHexAlpha: [null], - // colorFunction:[null], - // fontVariant: [null], - // @todo can be done using a callback, this is only used for Firefox < 35 - // filter: [null], - rem: ["rem"], - pseudoElements: ["css-gencontent"], - // pseudoClassMatches: [null], - // pseudoClassNot: [null], - colorRgba: ["css3-colors"], - // will always be null since autoprefixer does the same game as we do - // autoprefixer: [null] -} diff --git a/src/features.js b/src/features.js deleted file mode 100644 index e2cc122..0000000 --- a/src/features.js +++ /dev/null @@ -1,60 +0,0 @@ -export default { - // Reminder: order is important - customProperties(options) { - return require("postcss-custom-properties")(options) - }, - calc(options) { - return require("postcss-calc")(options) - }, - customMedia(options) { - return require("postcss-custom-media")(options) - }, - mediaQueriesRange(options) { - return require("postcss-media-minmax")(options) - }, - customSelectors(options) { - return require("postcss-custom-selectors")(options) - }, - colorRebeccapurple(options) { - return require("postcss-color-rebeccapurple")(options) - }, - colorHwb(options) { - return require("postcss-color-hwb")(options) - }, - colorGray(options) { - return require("postcss-color-gray")(options) - }, - colorHexAlpha(options) { - return require("postcss-color-hex-alpha")(options) - }, - colorFunction(options) { - return require("postcss-color-function")(options) - }, - fontVariant(options) { - return require("postcss-font-variant")(options) - }, - filter(options) { - return require("pleeease-filters")(options) - }, - rem(options) { - return require("pixrem")(options) - }, - pseudoElements(options) { - return require("postcss-pseudoelements")(options) - }, - pseudoClassMatches(options) { - return require("postcss-selector-matches")(options) - }, - pseudoClassNot(options) { - return require("postcss-selector-not")(options) - }, - pseudoClassAnyLink(options) { - return require("postcss-pseudo-class-any-link")(options) - }, - colorRgba(options) { - return require("postcss-color-rgba-fallback")(options) - }, - autoprefixer(options) { - return require("autoprefixer-core")(options) - }, -} diff --git a/src/fixes/custom-selectors-missing-colon.js b/src/fixes/custom-selectors-missing-colon.js deleted file mode 100644 index 8864561..0000000 --- a/src/fixes/custom-selectors-missing-colon.js +++ /dev/null @@ -1,41 +0,0 @@ -import postcss from "postcss" - -export default postcss.plugin( - "cssnext", - () => { - const cs = "@custom-selector" - - return (styles, result) => { - let alert = false - styles.eachAtRule("custom-selector", rule => { - if (rule.params.indexOf("--") === 0) { - - // display big warning once - if (!alert) { - alert = true - result.warn( - `Previously ${ cs } were working with and without pseudo ` + - `syntax ':'. Now you must use '${ cs } :--{name}' syntax ` + - `instead of '${ cs } --{name}'. The support of ` + - `syntax without ':' and this warning will be remove in the ` + - `next major release.` - ) - } - - result.warn( - [ - `Incorrect syntax for ${ cs }.`, - ` ${ cs } ${ rule.params }`, - `Should be:`, - ` ${ cs } :${ rule.params }`, - ].join("\n\n"), - {node: rule} - ) - - // fix for postcss-custom-selectors 2.x - rule.params = ":" + rule.params - } - }) - } - } -) diff --git a/src/fixes/index.js b/src/fixes/index.js deleted file mode 100644 index 5703b85..0000000 --- a/src/fixes/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import customSelectorsMissingColon from "./custom-selectors-missing-colon" - -export default { - customSelectorsMissingColon, -} diff --git a/src/index.js b/src/index.js index bb915a8..f6041dd 100644 --- a/src/index.js +++ b/src/index.js @@ -1,195 +1,10 @@ -import fs from "fs" +import postcss from "postcss" -import postCSS from "postcss" -import {isSupported} from "caniuse-api" +export default postcss.plugin("postcss-cssnext", (options) => { + options = { ...options } -import fixes from "./fixes" + // return (css, result) => { + return () => { -import libraryFeatures from "./features" -import featuresActivationMap from "./features-activation-map" - -import optionMessages from "./option.messages" - -/** - * Process a CSS `string` - * - * @param {String} string (optional) - * @param {Object} options (optional) - * @return {String} if string is given, or {Object} (postcss instance) - */ -function cssnext(string, options) { - // prevent usage as a webpack loader - // webpack run loader as function with an object as context - // this object contains a "webpack" key set to true if used as a loader - // https://github.com/cssnext/cssnext/issues/61 - if (typeof this === "object" && this.webpack === true) { - throw new Error( - "⚠︎ Don't use directly cssnext as a webpack loader. " + - "Please use `cssnext-loader` instead: " + - "https://github.com/cssnext/cssnext-loader" - ) - } - - if (arguments.length === 0) { - options = {} - } - if (arguments.length === 1 && typeof string === "object") { - options = string - string = undefined - } - else { - options = options || {} - } - - options = { - features: {}, - // options.browsers is deliberately undefined by defaut to inherit - // browserslist default behavior - // default sourcemap - // if `map` option is passed, `sourcemap` option is ignored - // if `sourcemap` option is passed, a inline map is used - map: (options.sourcemap ? true : null), - messages: true, - ...options, - } - - const features = options.features - - // propagate browsers option to autoprefixer - if (features.autoprefixer !== false) { - features.autoprefixer = { - browsers: ( - features.autoprefixer && features.autoprefixer.browsers - ? features.autoprefixer.browsers - : options.browsers - ), - ...(features.autoprefixer || {}), - } - - // autoprefixer doesn't like an "undefined" value. Related to coffee ? - if (features.autoprefixer.browsers === undefined) { - delete features.autoprefixer.browsers - } - } - - const postcss = postCSS() - - // only enable import & url if fs module is available - if (fs && fs.readFile) { - // @import - if (options.import !== false) { - const plugin = require("postcss-import")( - typeof options.import === "object" - ? {...options.import} - : undefined - ) - postcss.use(plugin) - } - - // url() adjustements - if (options.url !== false) { - const plugin = require("postcss-url")( - typeof options.url === "object" - ? {...options.url} - : undefined - ) - postcss.use(plugin) - } - } - - // tmp fixes - Object.keys(fixes).forEach(key => postcss.use(fixes[key])) - - // features - Object.keys(cssnext.features).forEach(key => { - // feature is auto enabled if: not disable && (enabled || no data yet || - // !supported yet) - if ( - // feature is not disabled - features[key] !== false && - ( - // feature is enabled - features[key] === true || - - // feature don't have any browsers data (yet) - featuresActivationMap[key] === undefined || - - // feature is not yet supported by the browsers scope - ( - featuresActivationMap[key] && - featuresActivationMap[key][0] && - !isSupported(featuresActivationMap[key][0], options.browsers) - ) - ) - ) { - const plugin = cssnext.features[key]( - typeof features[key] === "object" - ? {...features[key]} - : undefined - ) - postcss.use(plugin) - } - }) - - if (options.plugins) { - if (!Array.isArray(options.plugins)) { - throw new Error( - "cssnext 'plugins' option expect an array of PostCSS plugins. " + - "You provided " + (typeof options.plugins) - ) - } - - options.plugins.forEach(plugin => postcss.use(plugin)) - } - - // minification - if (options.compress) { - postcss.use( - require("cssnano")( - typeof options.compress === "object" - ? options.compress - : {} - ) - ) } - - // console plugins MUST be called after others because - // by default it remove messages from the registry - // (which make sense) - if (options.messages) { - optionMessages(options).forEach(plugin => { - postcss.use(plugin) - }) - } - - // classic API if string is passed - if (typeof string === "string") { - const result = postcss.process(string, options) - - // default behavior, cssnext returns a css string if no or inline sourcemap - if (options.map === null || (options.map === true || options.map.inline)) { - return result.css - } - - // if a specific map has been asked, we are returning css + map - return result - } - // or return the postcss instance that can be consumed as a postcss plugin - else { - return postcss - } -} - -/** - * Expose cssnext features - * - * @type {Object} - */ -cssnext.features = libraryFeatures - -/** - * Expose cssnext - * - * @type {Function} - */ -module.exports = cssnext +}) diff --git a/src/option.messages.browser.styles.js b/src/option.messages.browser.styles.js deleted file mode 100644 index 43c797a..0000000 --- a/src/option.messages.browser.styles.js +++ /dev/null @@ -1,52 +0,0 @@ -// not using fs for in browser usage (playground) -// -// source: http://iconmonstr.com/warning-3-icon/ -/* eslint-disable max-len */ -const svgGradient = ` - - - - -` -const warningSVG = ` - - ${ svgGradient } - - -`.trim() -/* eslint-enable max-len */ - -export default { - display: "block", - "white-space": "pre-wrap", - - // not a problem for old browsers, box will still be on top of body - position: "fixed", - top: 0, - left: 0, - right: 0, - "z-index": 10000, // just in case you know - - "font-size": ".9em", - padding: "1.5em 1em 1.5em 4.5em", // padding + background image padding - - color: "#318edf", - "background-color": "#fff", - - background: ( - `url( - "data:image/svg+xml;charset=utf-8,${encodeURIComponent(warningSVG)}" - ) 1em 1em / 2.5em 2.5em no-repeat, #fff` - ), - - // sugar - "border-bottom": "4px solid #318edf", - "box-shadow": "0 0 .6em rgba(0,0,0, .25)", - - // nice font - "font-family": "Menlo, Monaco, monospace", -} diff --git a/src/option.messages.js b/src/option.messages.js deleted file mode 100644 index 7e6d274..0000000 --- a/src/option.messages.js +++ /dev/null @@ -1,47 +0,0 @@ -import postcssMessagesConsole from "postcss-reporter" -// https://github.com/postcss/postcss-messages/issues/16 -// import postcssMessagesCSS from "postcss-messages" -import postcssMessagesCSS from "./plugins/messages" -import postcssMessageCSSstyles from "./option.messages.browser.styles.js" - -export default (options) => { - // true === all interfaces - if (options.messages === true) { - return [ - postcssMessagesCSS({styles: postcssMessageCSSstyles}), - postcssMessagesConsole, - ] - } - - // object: only the one you want - if (typeof options.messages === "object") { - return [ - ...options.messages.browser - ? [ - postcssMessagesCSS({ - styles: postcssMessageCSSstyles, - ...( - typeof options.messages.browser === "object" - ? options.messages.browser - : {} - ), - }), - ] - : [], - ...options.messages.console - ? [ - postcssMessagesConsole({ - ...( - typeof options.messages.console === "object" - ? options.messages.console - : {} - ), - }), - ] - : [], - ] - } - - // otherwise nothing :) - return [] -} diff --git a/src/plugins/messages.js b/src/plugins/messages.js deleted file mode 100644 index f8fbe8d..0000000 --- a/src/plugins/messages.js +++ /dev/null @@ -1,104 +0,0 @@ -// why this plugin ? -// https://github.com/postcss/postcss-messages/issues/16 - -import postcss from "postcss" -import colors from "chalk" - -// http://www.w3.org/TR/CSS2/syndata.html#characters -// tl;dr: escape as utf-16 all non ascii chars + new lines & quotes -function escapeForCSS(string) { - let newString = "" - for (let i = 0; i < string.length; i++) { - const ch = string.charAt(i) - switch (ch) { - case "\n": - case "\r": - newString += "\\A " - break - - case "\\": - case "\'": - case "\"": - newString += "\\" + ch - break - - default: - // non ascii - if (!ch.match(/^[\x00-\x7F]*$/)) { - let hexCh = string.charCodeAt(i).toString(16) - while (hexCh.length < 4) { - hexCh = "0" + hexCh - } - // space at the end is required - newString += "\\" + hexCh + " " - continue - } - newString += string[i] - } - } - - return newString -} - -export default postcss.plugin( - "postcss-messages", - (options) => { - options = { - ...options, - } - - if (options.disabled) { - return function() {} - } - - const defaultStyles = { - // ... - } - const styles = options.styles - ? options.styles - : defaultStyles - - return (css, result) => { - const messages = result.warnings() - if (messages.length === 0) { - return - } - - let selector = "html::before" - if (options.selector) { - selector = options.selector - } - else { - css.eachRule(rule => { - if ( - rule.selector === "html::before" || - rule.selector === "html:before" - ) { - selector = "html::after" - } - }) - } - - css.append({selector}) - Object.keys(styles).forEach(key => { - css.last.append({ - prop: key, - value: styles[key], - }) - }) - - const bullet = "›" - const content = messages.map(message => message.toString()) - .join(`\n\n\n${ bullet } `) - - css.last.append({ - prop: "content", - value: ( - "\"" + - escapeForCSS(`${ bullet } ${ colors.stripColor(content) }`) + - "\"" - ), - }) - } - } -) From 12db8ecb973f6fd1c401a62f8ec3ae6616d38175 Mon Sep 17 00:00:00 2001 From: Jed Mao Date: Wed, 9 Sep 2015 04:33:43 -0500 Subject: [PATCH 02/25] Add plugins --- package.json | 25 ++++++- .../fixtures/features/autoprefixer.css | 8 +++ .../features/autoprefixer.expected.css | 14 ++++ src/__tests__/fixtures/features/calc.css | 3 + .../fixtures/features/calc.expected.css | 3 + .../fixtures/features/color-function.css | 3 + .../features/color-function.expected.css | 3 + .../fixtures/features/color-gray.css | 3 + .../fixtures/features/color-gray.expected.css | 3 + .../fixtures/features/color-hex-alpha.css | 3 + .../features/color-hex-alpha.expected.css | 3 + src/__tests__/fixtures/features/color-hwb.css | 3 + .../fixtures/features/color-hwb.expected.css | 3 + .../fixtures/features/color-rebeccapurple.css | 3 + .../features/color-rebeccapurple.expected.css | 3 + .../fixtures/features/color-rgba.css | 4 ++ .../fixtures/features/color-rgba.expected.css | 6 ++ .../fixtures/features/custom-media.css | 5 ++ .../features/custom-media.expected.css | 5 ++ .../fixtures/features/custom-properties.css | 7 ++ .../features/custom-properties.expected.css | 5 ++ .../fixtures/features/custom-selectors.css | 5 ++ .../features/custom-selectors.expected.css | 8 +++ src/__tests__/fixtures/features/filter.css | 3 + .../fixtures/features/filter.expected.css | 4 ++ .../fixtures/features/font-variant.css | 7 ++ .../features/font-variant.expected.css | 9 +++ .../fixtures/features/media-queries-range.css | 2 + .../features/media-queries-range.expected.css | 2 + .../features/pseudo-class-any-link.css | 3 + .../pseudo-class-any-link.expected.css | 3 + .../features/pseudo-class-matches.css | 3 + .../pseudo-class-matches.expected.css | 3 + .../fixtures/features/pseudo-class-not.css | 3 + .../features/pseudo-class-not.expected.css | 3 + .../fixtures/features/pseudo-elements.css | 6 ++ .../features/pseudo-elements.expected.css | 6 ++ src/__tests__/fixtures/features/rem.css | 11 ++++ .../fixtures/features/rem.expected.css | 12 ++++ src/__tests__/option.features.js | 62 +++++++++++++++++ src/__tests__/utils/index.js | 33 ++++++++++ src/features-activation-map.js | 29 ++++++++ src/features.js | 60 +++++++++++++++++ src/index.js | 66 ++++++++++++++++++- 44 files changed, 453 insertions(+), 5 deletions(-) create mode 100644 src/__tests__/fixtures/features/autoprefixer.css create mode 100644 src/__tests__/fixtures/features/autoprefixer.expected.css create mode 100644 src/__tests__/fixtures/features/calc.css create mode 100644 src/__tests__/fixtures/features/calc.expected.css create mode 100644 src/__tests__/fixtures/features/color-function.css create mode 100644 src/__tests__/fixtures/features/color-function.expected.css create mode 100644 src/__tests__/fixtures/features/color-gray.css create mode 100644 src/__tests__/fixtures/features/color-gray.expected.css create mode 100644 src/__tests__/fixtures/features/color-hex-alpha.css create mode 100644 src/__tests__/fixtures/features/color-hex-alpha.expected.css create mode 100644 src/__tests__/fixtures/features/color-hwb.css create mode 100644 src/__tests__/fixtures/features/color-hwb.expected.css create mode 100644 src/__tests__/fixtures/features/color-rebeccapurple.css create mode 100644 src/__tests__/fixtures/features/color-rebeccapurple.expected.css create mode 100644 src/__tests__/fixtures/features/color-rgba.css create mode 100644 src/__tests__/fixtures/features/color-rgba.expected.css create mode 100644 src/__tests__/fixtures/features/custom-media.css create mode 100644 src/__tests__/fixtures/features/custom-media.expected.css create mode 100644 src/__tests__/fixtures/features/custom-properties.css create mode 100644 src/__tests__/fixtures/features/custom-properties.expected.css create mode 100644 src/__tests__/fixtures/features/custom-selectors.css create mode 100644 src/__tests__/fixtures/features/custom-selectors.expected.css create mode 100644 src/__tests__/fixtures/features/filter.css create mode 100644 src/__tests__/fixtures/features/filter.expected.css create mode 100644 src/__tests__/fixtures/features/font-variant.css create mode 100644 src/__tests__/fixtures/features/font-variant.expected.css create mode 100644 src/__tests__/fixtures/features/media-queries-range.css create mode 100644 src/__tests__/fixtures/features/media-queries-range.expected.css create mode 100644 src/__tests__/fixtures/features/pseudo-class-any-link.css create mode 100644 src/__tests__/fixtures/features/pseudo-class-any-link.expected.css create mode 100644 src/__tests__/fixtures/features/pseudo-class-matches.css create mode 100644 src/__tests__/fixtures/features/pseudo-class-matches.expected.css create mode 100644 src/__tests__/fixtures/features/pseudo-class-not.css create mode 100644 src/__tests__/fixtures/features/pseudo-class-not.expected.css create mode 100644 src/__tests__/fixtures/features/pseudo-elements.css create mode 100644 src/__tests__/fixtures/features/pseudo-elements.expected.css create mode 100644 src/__tests__/fixtures/features/rem.css create mode 100644 src/__tests__/fixtures/features/rem.expected.css create mode 100644 src/__tests__/option.features.js create mode 100644 src/__tests__/utils/index.js create mode 100644 src/features-activation-map.js create mode 100644 src/features.js diff --git a/package.json b/package.json index a74ed1d..2e9882d 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,27 @@ "!**/__tests__" ], "dependencies": { - "postcss": "^5.0.4" + "autoprefixer": "^6.0.2", + "caniuse-api": "^1.3.2", + "pixrem": "^2.0.0", + "pleeease-filters": "^1.0.1", + "postcss": "^5.0.4", + "postcss-calc": "^5.0.0", + "postcss-color-function": "^2.0.0", + "postcss-color-gray": "^3.0.0", + "postcss-color-hex-alpha": "^2.0.0", + "postcss-color-hwb": "^2.0.0", + "postcss-color-rebeccapurple": "^2.0.0", + "postcss-color-rgba-fallback": "^2.0.0", + "postcss-custom-media": "^5.0.0", + "postcss-custom-properties": "^5.0.0", + "postcss-custom-selectors": "^3.0.0", + "postcss-font-variant": "^2.0.0", + "postcss-media-minmax": "^2.1.0", + "postcss-pseudo-class-any-link": "^1.0.0", + "postcss-pseudoelements": "^3.0.0", + "postcss-selector-matches": "^2.0.0", + "postcss-selector-not": "^2.0.0" }, "devDependencies": { "babel": "^5.8.23", @@ -74,7 +94,8 @@ "tape": "^4.2.0", "webpack": "^1.9.7", "webpack-dev-server": "^1.8.2", - "webpack-nano-logs": "^1.0.0" + "webpack-nano-logs": "^1.0.0", + "to-slug-case": "^0.1.2" }, "scripts": { "prebabelify": "rimraf lib", diff --git a/src/__tests__/fixtures/features/autoprefixer.css b/src/__tests__/fixtures/features/autoprefixer.css new file mode 100644 index 0000000..4954ce0 --- /dev/null +++ b/src/__tests__/fixtures/features/autoprefixer.css @@ -0,0 +1,8 @@ +* { + transition: transform 1s; +} + +@keyframes spin { + 0% { transform: rotate(0deg) } + 100% { transform: rotate(360deg) } +} diff --git a/src/__tests__/fixtures/features/autoprefixer.expected.css b/src/__tests__/fixtures/features/autoprefixer.expected.css new file mode 100644 index 0000000..175ed52 --- /dev/null +++ b/src/__tests__/fixtures/features/autoprefixer.expected.css @@ -0,0 +1,14 @@ +* { + -webkit-transition: -webkit-transform 1s; + transition: transform 1s; +} + +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg) } + 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg) } +} + +@keyframes spin { + 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg) } + 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg) } +} diff --git a/src/__tests__/fixtures/features/calc.css b/src/__tests__/fixtures/features/calc.css new file mode 100644 index 0000000..3fe0415 --- /dev/null +++ b/src/__tests__/fixtures/features/calc.css @@ -0,0 +1,3 @@ +html { + font-size: calc(1em * 2) +} diff --git a/src/__tests__/fixtures/features/calc.expected.css b/src/__tests__/fixtures/features/calc.expected.css new file mode 100644 index 0000000..b7a57f1 --- /dev/null +++ b/src/__tests__/fixtures/features/calc.expected.css @@ -0,0 +1,3 @@ +html { + font-size: 2em +} diff --git a/src/__tests__/fixtures/features/color-function.css b/src/__tests__/fixtures/features/color-function.css new file mode 100644 index 0000000..380f915 --- /dev/null +++ b/src/__tests__/fixtures/features/color-function.css @@ -0,0 +1,3 @@ +body { + background: color(rgb(102, 51, 153) a(90%)) +} diff --git a/src/__tests__/fixtures/features/color-function.expected.css b/src/__tests__/fixtures/features/color-function.expected.css new file mode 100644 index 0000000..b189789 --- /dev/null +++ b/src/__tests__/fixtures/features/color-function.expected.css @@ -0,0 +1,3 @@ +body { + background: rgba(102, 51, 153, 0.9) +} diff --git a/src/__tests__/fixtures/features/color-gray.css b/src/__tests__/fixtures/features/color-gray.css new file mode 100644 index 0000000..5e7b691 --- /dev/null +++ b/src/__tests__/fixtures/features/color-gray.css @@ -0,0 +1,3 @@ +.bar { + color: gray(255, 50%); +} diff --git a/src/__tests__/fixtures/features/color-gray.expected.css b/src/__tests__/fixtures/features/color-gray.expected.css new file mode 100644 index 0000000..94281e7 --- /dev/null +++ b/src/__tests__/fixtures/features/color-gray.expected.css @@ -0,0 +1,3 @@ +.bar { + color: rgba(255, 255, 255, 0.5); +} diff --git a/src/__tests__/fixtures/features/color-hex-alpha.css b/src/__tests__/fixtures/features/color-hex-alpha.css new file mode 100644 index 0000000..9c3dd4d --- /dev/null +++ b/src/__tests__/fixtures/features/color-hex-alpha.css @@ -0,0 +1,3 @@ +body { + background: #9d9c +} diff --git a/src/__tests__/fixtures/features/color-hex-alpha.expected.css b/src/__tests__/fixtures/features/color-hex-alpha.expected.css new file mode 100644 index 0000000..3a2605a --- /dev/null +++ b/src/__tests__/fixtures/features/color-hex-alpha.expected.css @@ -0,0 +1,3 @@ +body { + background: rgba(153, 221, 153, 0.8) +} diff --git a/src/__tests__/fixtures/features/color-hwb.css b/src/__tests__/fixtures/features/color-hwb.css new file mode 100644 index 0000000..5019bc0 --- /dev/null +++ b/src/__tests__/fixtures/features/color-hwb.css @@ -0,0 +1,3 @@ +body { + background: hwb(0, 20%, 40%) +} diff --git a/src/__tests__/fixtures/features/color-hwb.expected.css b/src/__tests__/fixtures/features/color-hwb.expected.css new file mode 100644 index 0000000..9cc2d1f --- /dev/null +++ b/src/__tests__/fixtures/features/color-hwb.expected.css @@ -0,0 +1,3 @@ +body { + background: rgb(153, 51, 51) +} diff --git a/src/__tests__/fixtures/features/color-rebeccapurple.css b/src/__tests__/fixtures/features/color-rebeccapurple.css new file mode 100644 index 0000000..33dc9bb --- /dev/null +++ b/src/__tests__/fixtures/features/color-rebeccapurple.css @@ -0,0 +1,3 @@ +body { + background: rebeccapurple +} diff --git a/src/__tests__/fixtures/features/color-rebeccapurple.expected.css b/src/__tests__/fixtures/features/color-rebeccapurple.expected.css new file mode 100644 index 0000000..17739fc --- /dev/null +++ b/src/__tests__/fixtures/features/color-rebeccapurple.expected.css @@ -0,0 +1,3 @@ +body { + background: rgb(102, 51, 153) +} diff --git a/src/__tests__/fixtures/features/color-rgba.css b/src/__tests__/fixtures/features/color-rgba.css new file mode 100644 index 0000000..42d8d13 --- /dev/null +++ b/src/__tests__/fixtures/features/color-rgba.css @@ -0,0 +1,4 @@ +.foo { + background: rgba(153, 221, 153, 0.8); + border: solid 1px rgba(100,102,103,.3); +} diff --git a/src/__tests__/fixtures/features/color-rgba.expected.css b/src/__tests__/fixtures/features/color-rgba.expected.css new file mode 100644 index 0000000..013f935 --- /dev/null +++ b/src/__tests__/fixtures/features/color-rgba.expected.css @@ -0,0 +1,6 @@ +.foo { + background: #99DD99; + background: rgba(153, 221, 153, 0.8); + border: solid 1px #646667; + border: solid 1px rgba(100,102,103,.3); +} diff --git a/src/__tests__/fixtures/features/custom-media.css b/src/__tests__/fixtures/features/custom-media.css new file mode 100644 index 0000000..bacd858 --- /dev/null +++ b/src/__tests__/fixtures/features/custom-media.css @@ -0,0 +1,5 @@ +@custom-media --small-viewport (max-width: 30em); + +@media (--small-viewport) { + /* styles for small viewport */ +} diff --git a/src/__tests__/fixtures/features/custom-media.expected.css b/src/__tests__/fixtures/features/custom-media.expected.css new file mode 100644 index 0000000..ee9d211 --- /dev/null +++ b/src/__tests__/fixtures/features/custom-media.expected.css @@ -0,0 +1,5 @@ + + +@media (max-width: 30em) { + /* styles for small viewport */ +} diff --git a/src/__tests__/fixtures/features/custom-properties.css b/src/__tests__/fixtures/features/custom-properties.css new file mode 100644 index 0000000..65c688e --- /dev/null +++ b/src/__tests__/fixtures/features/custom-properties.css @@ -0,0 +1,7 @@ +:root { + --color: #e00 +} + +body { + color: var(--color) +} diff --git a/src/__tests__/fixtures/features/custom-properties.expected.css b/src/__tests__/fixtures/features/custom-properties.expected.css new file mode 100644 index 0000000..18ddf03 --- /dev/null +++ b/src/__tests__/fixtures/features/custom-properties.expected.css @@ -0,0 +1,5 @@ + + +body { + color: #e00 +} diff --git a/src/__tests__/fixtures/features/custom-selectors.css b/src/__tests__/fixtures/features/custom-selectors.css new file mode 100644 index 0000000..b7e7a40 --- /dev/null +++ b/src/__tests__/fixtures/features/custom-selectors.css @@ -0,0 +1,5 @@ +@custom-selector :--heading h1, h2, h3, h4, h5, h6; + +article :--heading + p{ + margin-top: 0; +} diff --git a/src/__tests__/fixtures/features/custom-selectors.expected.css b/src/__tests__/fixtures/features/custom-selectors.expected.css new file mode 100644 index 0000000..fdac390 --- /dev/null +++ b/src/__tests__/fixtures/features/custom-selectors.expected.css @@ -0,0 +1,8 @@ +article h1 + p, +article h2 + p, +article h3 + p, +article h4 + p, +article h5 + p, +article h6 + p{ + margin-top: 0; +} diff --git a/src/__tests__/fixtures/features/filter.css b/src/__tests__/fixtures/features/filter.css new file mode 100644 index 0000000..d7fa2b7 --- /dev/null +++ b/src/__tests__/fixtures/features/filter.css @@ -0,0 +1,3 @@ +.blur { + filter: blur(4px); +} diff --git a/src/__tests__/fixtures/features/filter.expected.css b/src/__tests__/fixtures/features/filter.expected.css new file mode 100644 index 0000000..c4d1b58 --- /dev/null +++ b/src/__tests__/fixtures/features/filter.expected.css @@ -0,0 +1,4 @@ +.blur { + filter: url('data:image/svg+xml;charset=utf-8,#filter'); + filter: blur(4px); +} diff --git a/src/__tests__/fixtures/features/font-variant.css b/src/__tests__/fixtures/features/font-variant.css new file mode 100644 index 0000000..d561bf1 --- /dev/null +++ b/src/__tests__/fixtures/features/font-variant.css @@ -0,0 +1,7 @@ +h2 { + font-variant-caps: small-caps; +} + +table { + font-variant-numeric: lining-nums; +} diff --git a/src/__tests__/fixtures/features/font-variant.expected.css b/src/__tests__/fixtures/features/font-variant.expected.css new file mode 100644 index 0000000..2e13f35 --- /dev/null +++ b/src/__tests__/fixtures/features/font-variant.expected.css @@ -0,0 +1,9 @@ +h2 { + font-feature-settings: "c2sc"; + font-variant-caps: small-caps; +} + +table { + font-feature-settings: "lnum"; + font-variant-numeric: lining-nums; +} diff --git a/src/__tests__/fixtures/features/media-queries-range.css b/src/__tests__/fixtures/features/media-queries-range.css new file mode 100644 index 0000000..e87927a --- /dev/null +++ b/src/__tests__/fixtures/features/media-queries-range.css @@ -0,0 +1,2 @@ +@media screen and (width >= 500px) and (width <= 1200px) {} +@media screen and (500px <= width <= 1200px) {} diff --git a/src/__tests__/fixtures/features/media-queries-range.expected.css b/src/__tests__/fixtures/features/media-queries-range.expected.css new file mode 100644 index 0000000..bf82f6f --- /dev/null +++ b/src/__tests__/fixtures/features/media-queries-range.expected.css @@ -0,0 +1,2 @@ +@media screen and (min-width: 500px) and (max-width: 1200px) {} +@media screen and (min-width: 500px) and (max-width: 1200px) {} diff --git a/src/__tests__/fixtures/features/pseudo-class-any-link.css b/src/__tests__/fixtures/features/pseudo-class-any-link.css new file mode 100644 index 0000000..7cc79d6 --- /dev/null +++ b/src/__tests__/fixtures/features/pseudo-class-any-link.css @@ -0,0 +1,3 @@ +nav :any-link > span { + background-color: yellow; +} diff --git a/src/__tests__/fixtures/features/pseudo-class-any-link.expected.css b/src/__tests__/fixtures/features/pseudo-class-any-link.expected.css new file mode 100644 index 0000000..4485199 --- /dev/null +++ b/src/__tests__/fixtures/features/pseudo-class-any-link.expected.css @@ -0,0 +1,3 @@ +nav :link > span,nav :visited > span { + background-color: yellow; +} diff --git a/src/__tests__/fixtures/features/pseudo-class-matches.css b/src/__tests__/fixtures/features/pseudo-class-matches.css new file mode 100644 index 0000000..ebfa974 --- /dev/null +++ b/src/__tests__/fixtures/features/pseudo-class-matches.css @@ -0,0 +1,3 @@ +p:matches(:first-child, .specific) { + color: red; +} diff --git a/src/__tests__/fixtures/features/pseudo-class-matches.expected.css b/src/__tests__/fixtures/features/pseudo-class-matches.expected.css new file mode 100644 index 0000000..7dba525 --- /dev/null +++ b/src/__tests__/fixtures/features/pseudo-class-matches.expected.css @@ -0,0 +1,3 @@ +p:first-child, p.specific { + color: red; +} diff --git a/src/__tests__/fixtures/features/pseudo-class-not.css b/src/__tests__/fixtures/features/pseudo-class-not.css new file mode 100644 index 0000000..b770fd4 --- /dev/null +++ b/src/__tests__/fixtures/features/pseudo-class-not.css @@ -0,0 +1,3 @@ +p:not(:first-child, .specific) { + background: blue; +} diff --git a/src/__tests__/fixtures/features/pseudo-class-not.expected.css b/src/__tests__/fixtures/features/pseudo-class-not.expected.css new file mode 100644 index 0000000..0a99017 --- /dev/null +++ b/src/__tests__/fixtures/features/pseudo-class-not.expected.css @@ -0,0 +1,3 @@ +p:not(:first-child):not(.specific) { + background: blue; +} diff --git a/src/__tests__/fixtures/features/pseudo-elements.css b/src/__tests__/fixtures/features/pseudo-elements.css new file mode 100644 index 0000000..e924841 --- /dev/null +++ b/src/__tests__/fixtures/features/pseudo-elements.css @@ -0,0 +1,6 @@ +.foo::after { + content:"pseudoelement" +} +.foo::before { + content:"pseudoelement" +} diff --git a/src/__tests__/fixtures/features/pseudo-elements.expected.css b/src/__tests__/fixtures/features/pseudo-elements.expected.css new file mode 100644 index 0000000..aa56a6b --- /dev/null +++ b/src/__tests__/fixtures/features/pseudo-elements.expected.css @@ -0,0 +1,6 @@ +.foo:after { + content:"pseudoelement" +} +.foo:before { + content:"pseudoelement" +} diff --git a/src/__tests__/fixtures/features/rem.css b/src/__tests__/fixtures/features/rem.css new file mode 100644 index 0000000..dcddbf3 --- /dev/null +++ b/src/__tests__/fixtures/features/rem.css @@ -0,0 +1,11 @@ +.sky { + margin: 2.5rem 2px 3em 100%; + color: blue; +} + +@media screen and (min-width: 20rem) { + .leaf { + margin-bottom: 1.333rem; + font-size: 1.5rem; + } +} \ No newline at end of file diff --git a/src/__tests__/fixtures/features/rem.expected.css b/src/__tests__/fixtures/features/rem.expected.css new file mode 100644 index 0000000..b18fb60 --- /dev/null +++ b/src/__tests__/fixtures/features/rem.expected.css @@ -0,0 +1,12 @@ +.sky { + margin: 40px 2px 3em 100%; + margin: 2.5rem 2px 3em 100%; + color: blue; +} + +@media screen and (min-width: 20rem) { + .leaf { + margin-bottom: 1.333rem; + font-size: 1.5rem; + } +} \ No newline at end of file diff --git a/src/__tests__/option.features.js b/src/__tests__/option.features.js new file mode 100644 index 0000000..9468ab7 --- /dev/null +++ b/src/__tests__/option.features.js @@ -0,0 +1,62 @@ +/** + * Test dependencies + */ +import test from "tape" +import { join } from "path" + +import utils from "./utils" +import cssnext, { features } from ".." + +/** + * Features tests + */ +import toSlug from "to-slug-case" +const testFeature = function( + t, + feature, + version, + source, + input, + expected +) { + const options = { features: { } } + + // disable all features + Object.keys(features).forEach(function(key) { + options.features[key] = false + }) + + const css = cssnext(options).process(input).css + t.notEqual( + css, + expected, + version + ": should not add " + feature + " support if disabled" + ) + t.equal( + css, + input, + version + ": should not modify input if " + feature + " is disabled" + ) + + // enable only the one we want to test... + options.features[feature] = true + + t.equal( + cssnext(options).process(input).css.trim(), + expected.trim(), + version + ": should add " + feature + " support" + ) +} + +Object.keys(features).forEach(function(name) { + const slug = toSlug(name) + const source = utils.fixturePath(join("features", slug)) + const input = utils.readFixture(join("features", slug)) + const expected = utils.readFixture(join("features", slug + ".expected")) + + test(slug, function(t) { + testFeature(t, name, "node.js", source, input, expected) + + t.end() + }) +}) diff --git a/src/__tests__/utils/index.js b/src/__tests__/utils/index.js new file mode 100644 index 0000000..12eda95 --- /dev/null +++ b/src/__tests__/utils/index.js @@ -0,0 +1,33 @@ +/** + * Module dependencies + */ +import fs from "fs" +import { join } from "path" + +/** + * Exposes functions + * + * @type {Object} + */ +export default { + /** + * get fixture path + * @param {String} name + * @param {String} ext (optional extension, default to ".css") + * @return the fixture filename + */ + fixturePath(name, ext) { + ext = (ext !== undefined ? ext : ".css") + return join("src", "__tests__", "fixtures", name + ext) + }, + + /** + * read a fixture + * @param {String} name + * @param {String} ext (optional extension, default to ".css") + * @return the fixture content + */ + readFixture(name, ext) { + return fs.readFileSync(this.fixturePath(name, ext), "utf8") + }, +} diff --git a/src/features-activation-map.js b/src/features-activation-map.js new file mode 100644 index 0000000..e6f5568 --- /dev/null +++ b/src/features-activation-map.js @@ -0,0 +1,29 @@ +// Some features might affect others (eg: var() in a calc() +// in order to prevent issue, the map contains a sort of dependencies list +// +// null == always enable (& no caniuse data) +export default { + customProperties: [ "css-variables" ], + // calc() transformation only make sense with transformed custom properties, + // don't you think ? + // calc: null, + // @todo open PR on caniuse repo https://github.com/Fyrd/caniuse + // customMedia: [ null ], + // mediaQueriesRange: [ null ], + // customSelectors: [ null ], + // colorRebeccapurple: [ null ], // @todo can be done easily + // colorHwb: [ null ], + // colorGray: [ null ], + // colorHexAlpha: [ null ], + // colorFunction:[ null], + // fontVariant: [ null ], + // @todo can be done using a callback, this is only used for Firefox < 35 + // filter: [ null ], + rem: [ "rem" ], + pseudoElements: [ "css-gencontent" ], + // pseudoClassMatches: [ null ], + // pseudoClassNot: [ null ], + colorRgba: [ "css3-colors" ], + // will always be null since autoprefixer does the same game as we do + // autoprefixer: [ null ] +} diff --git a/src/features.js b/src/features.js new file mode 100644 index 0000000..b2cfe1e --- /dev/null +++ b/src/features.js @@ -0,0 +1,60 @@ +export default { + // Reminder: order is important + customProperties(options) { + return require("postcss-custom-properties")(options) + }, + calc(options) { + return require("postcss-calc")(options) + }, + customMedia(options) { + return require("postcss-custom-media")(options) + }, + mediaQueriesRange(options) { + return require("postcss-media-minmax")(options) + }, + customSelectors(options) { + return require("postcss-custom-selectors")(options) + }, + colorRebeccapurple(options) { + return require("postcss-color-rebeccapurple")(options) + }, + colorHwb(options) { + return require("postcss-color-hwb")(options) + }, + colorGray(options) { + return require("postcss-color-gray")(options) + }, + colorHexAlpha(options) { + return require("postcss-color-hex-alpha")(options) + }, + colorFunction(options) { + return require("postcss-color-function")(options) + }, + fontVariant(options) { + return require("postcss-font-variant")(options) + }, + filter(options) { + return require("pleeease-filters")(options) + }, + rem(options) { + return require("pixrem")(options) + }, + pseudoElements(options) { + return require("postcss-pseudoelements")(options) + }, + pseudoClassMatches(options) { + return require("postcss-selector-matches")(options) + }, + pseudoClassNot(options) { + return require("postcss-selector-not")(options) + }, + pseudoClassAnyLink(options) { + return require("postcss-pseudo-class-any-link")(options) + }, + colorRgba(options) { + return require("postcss-color-rgba-fallback")(options) + }, + autoprefixer(options) { + return require("autoprefixer")(options) + }, +} diff --git a/src/index.js b/src/index.js index f6041dd..bf8a7d5 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,70 @@ import postcss from "postcss" +import { isSupported } from "caniuse-api" + +import libraryFeatures from "./features" +import featuresActivationMap from "./features-activation-map" + +export { libraryFeatures as features } export default postcss.plugin("postcss-cssnext", (options) => { - options = { ...options } + options = { + features: {}, + // options.browsers is deliberately undefined by default to inherit + // browserslist default behavior + ...options, + } - // return (css, result) => { - return () => { + const features = options.features + // propagate browsers option to autoprefixer + if (features.autoprefixer !== false) { + features.autoprefixer = { + browsers: ( + features.autoprefixer && features.autoprefixer.browsers + ? features.autoprefixer.browsers + : options.browsers + ), + ...(features.autoprefixer || {}), + } + + // autoprefixer doesn't like an "undefined" value. Related to coffee ? + if (features.autoprefixer.browsers === undefined) { + delete features.autoprefixer.browsers + } } + + const processor = postcss() + + // features + Object.keys(libraryFeatures).forEach(key => { + // feature is auto enabled if: not disable && (enabled || no data yet || + // !supported yet) + if ( + // feature is not disabled + features[key] !== false && + ( + // feature is enabled + features[key] === true || + + // feature don't have any browsers data (yet) + featuresActivationMap[key] === undefined || + + // feature is not yet supported by the browsers scope + ( + featuresActivationMap[key] && + featuresActivationMap[key][0] && + !isSupported(featuresActivationMap[key][0], options.browsers) + ) + ) + ) { + const plugin = libraryFeatures[key]( + typeof features[key] === "object" + ? { ...features[key] } + : undefined + ) + processor.use(plugin) + } + }) + + return processor }) From 1c65ee7e6f0ca81600da57e5ee9e064f7a97a0d0 Mon Sep 17 00:00:00 2001 From: Jed Mao Date: Thu, 10 Sep 2015 00:54:29 -0500 Subject: [PATCH 03/25] Test browsers option --- src/__tests__/option.browsers.js | 62 ++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/__tests__/option.browsers.js diff --git a/src/__tests__/option.browsers.js b/src/__tests__/option.browsers.js new file mode 100644 index 0000000..fbb3865 --- /dev/null +++ b/src/__tests__/option.browsers.js @@ -0,0 +1,62 @@ +import tape from "tape" + +import cssnext from ".." + +tape("cssnext browsers option", function(t) { + + // no recent browser need pixrem + const remInput = "body{font-size:2rem}" + t.equal( + cssnext({ browsers: "last 1 version" }).process(remInput).css, + remInput, + "should not enable px fallback when all browsers support it" + ) + + const customPropsInput = ":root{--foo:bar}baz{qux:var(--foo)}" + const customPropsOutput = "baz{qux: bar}" + + // fx 30 doesn't handle custom prop + t.equal( + cssnext({ browsers: "Firefox >= 30" }).process(customPropsInput).css, + customPropsOutput, + "should enable custom properties when browsers do not support it" + ) + + // fx 31 handle custom prop + t.equal( + cssnext({ browsers: "Firefox >= 31" }).process(customPropsInput).css, + customPropsInput, + "should NOT enable custom properties when browsers support it" + ) + + // fx 31 support but not IE 8 + t.equal( + cssnext({ browsers: "Firefox >= 31, IE 8" }).process(customPropsInput).css, + customPropsOutput, + "should enable custom properties when at least one browsers do not " + + "support it" + ) + + t.end() +}) + +tape("cssnext browsers option propagation", function(t) { + const input = "body{transition: 1s}" + const output = "body{-webkit-transition: 1s;transition: 1s}" + + // Safari 6 need -webkit prefix + t.equal( + cssnext({ browsers: "Safari 6" }).process(input).css, + output, + "should propagate browsers option to autoprefixer" + ) + + // Safari 6.1 do not need -webkit prefix + t.equal( + cssnext({ browsers: "Safari 6.1" }).process(input).css, + input, + "should propagate browsers option to autoprefixer" + ) + + t.end() +}) From 47c94de7f0446cd87a3cf1ad1fbb1edbf679ce40 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Thu, 10 Sep 2015 08:17:04 +0200 Subject: [PATCH 04/25] Prepare release + add some docs about WHY --- README.md | 37 +++++++++++++++++++++++++++++++- src/__tests__/option.features.js | 9 ++++---- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3e3f200..f64a90b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,42 @@ cssnext is a CSS transpiler that allows you to use the latest CSS syntax today. It transforms CSS specs into more compatible CSS so you don’t need to wait for browser support. -**This repository contains the PostCSS plugin.** +--- + +# This repository contains the PostCSS plugin. + +## Why **postcss-cssnext** ? What is the difference with **cssnext** ? + +cssnext was at first designed to be a complete tool, before PostCSS became +popular and so includes some options that does not really belong in a PostCSS +plugin (options like `import`, `url`, `compress`, `plugins`). +This days, most people use PostCSS directly so we decided to make integration of +cssnext more simple by providing a simple (real) plugin. + +If you were using cssnext with some options here is what you need to know: + +- `import`: just add in your plugins list + [postcss-import](https://github.com/postcss/postcss-import) +- `url`: just add in your plugins list + [postcss-url](https://github.com/postcss/postcss-url) +- `compress`: just add in your plugins list + [cssnano](https://github.com/ben-eb/cssnano) +- `plugins`: just add the plugins directly in your list +- `messages`: see + [postcss-reporter](https://github.com/postcss/postcss-reporter) + and + [postcss-browser-reporter](https://github.com/postcss/postcss-browser-reporter) +- `sourcemap`, `map`, `to`, `from`: see + [PostCSS source map documentation](https://github.com/postcss/postcss#source-map) + + +## But I like cssnext as it was ! + +_Don't worry. That's why we created another package._ +**cssnext** package will have a major release soon in order to introduce a minor +but breaking changes in the Node.js API, but you will get the same tool as +before. +The nice thing is: **cssnext** will use **postcss-cssnext** under the hood. --- diff --git a/src/__tests__/option.features.js b/src/__tests__/option.features.js index 9468ab7..3ed5a0f 100644 --- a/src/__tests__/option.features.js +++ b/src/__tests__/option.features.js @@ -14,7 +14,6 @@ import toSlug from "to-slug-case" const testFeature = function( t, feature, - version, source, input, expected @@ -30,12 +29,12 @@ const testFeature = function( t.notEqual( css, expected, - version + ": should not add " + feature + " support if disabled" + "should not add " + feature + " support if disabled" ) t.equal( css, input, - version + ": should not modify input if " + feature + " is disabled" + "should not modify input if " + feature + " is disabled" ) // enable only the one we want to test... @@ -44,7 +43,7 @@ const testFeature = function( t.equal( cssnext(options).process(input).css.trim(), expected.trim(), - version + ": should add " + feature + " support" + "should add " + feature + " support" ) } @@ -55,7 +54,7 @@ Object.keys(features).forEach(function(name) { const expected = utils.readFixture(join("features", slug + ".expected")) test(slug, function(t) { - testFeature(t, name, "node.js", source, input, expected) + testFeature(t, name, source, input, expected) t.end() }) From fbfb7e165e2f4c06cb5f4c801229f7b65e4a8c7e Mon Sep 17 00:00:00 2001 From: Jed Mao Date: Fri, 11 Sep 2015 01:44:27 -0500 Subject: [PATCH 05/25] Fix grammar, minor tweaks in readme --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index f64a90b..81e70a4 100644 --- a/README.md +++ b/README.md @@ -18,24 +18,24 @@ It transforms CSS specs into more compatible CSS so you don’t need to wait for ## Why **postcss-cssnext** ? What is the difference with **cssnext** ? cssnext was at first designed to be a complete tool, before PostCSS became -popular and so includes some options that does not really belong in a PostCSS -plugin (options like `import`, `url`, `compress`, `plugins`). -This days, most people use PostCSS directly so we decided to make integration of +popular; thus, includes some options that don't really belong in a PostCSS +plugin (e.g., `import`, `url`, `compress`, `plugins`). +These days, most people use PostCSS directly so we decided to make integration of cssnext more simple by providing a simple (real) plugin. If you were using cssnext with some options here is what you need to know: -- `import`: just add in your plugins list - [postcss-import](https://github.com/postcss/postcss-import) -- `url`: just add in your plugins list - [postcss-url](https://github.com/postcss/postcss-url) -- `compress`: just add in your plugins list - [cssnano](https://github.com/ben-eb/cssnano) +- `import`: just add into your plugins list + [`postcss-import`](https://github.com/postcss/postcss-import) +- `url`: just add into your plugins list + [`postcss-url`](https://github.com/postcss/postcss-url) +- `compress`: just add into your plugins list + [`cssnano`](https://github.com/ben-eb/cssnano) - `plugins`: just add the plugins directly in your list - `messages`: see - [postcss-reporter](https://github.com/postcss/postcss-reporter) + [`postcss-reporter`](https://github.com/postcss/postcss-reporter) and - [postcss-browser-reporter](https://github.com/postcss/postcss-browser-reporter) + [`postcss-browser-reporter`](https://github.com/postcss/postcss-browser-reporter) - `sourcemap`, `map`, `to`, `from`: see [PostCSS source map documentation](https://github.com/postcss/postcss#source-map) @@ -43,8 +43,8 @@ If you were using cssnext with some options here is what you need to know: ## But I like cssnext as it was ! _Don't worry. That's why we created another package._ -**cssnext** package will have a major release soon in order to introduce a minor -but breaking changes in the Node.js API, but you will get the same tool as +The **cssnext** package will have a major release soon in order to introduce a +minor but breaking changes in the Node.js API, but you will get the same tool as before. The nice thing is: **cssnext** will use **postcss-cssnext** under the hood. From 42e5cafae219ff0ddfb46c27021fa3c0595ccdd6 Mon Sep 17 00:00:00 2001 From: Jed Mao Date: Mon, 14 Sep 2015 03:55:46 -0500 Subject: [PATCH 06/25] pleeease-filters@2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2e9882d..36a4722 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "autoprefixer": "^6.0.2", "caniuse-api": "^1.3.2", "pixrem": "^2.0.0", - "pleeease-filters": "^1.0.1", + "pleeease-filters": "^2.0.0", "postcss": "^5.0.4", "postcss-calc": "^5.0.0", "postcss-color-function": "^2.0.0", From b720b8cedf859fc558e9f3ea9a528ef84460ca3e Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Mon, 14 Sep 2015 14:23:24 +0200 Subject: [PATCH 07/25] Add 2.0.0 publish date into CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20bc48c..b0b052d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 2.0.0 - Unreleased +# 2.0.0 - 2015-09-14 - Added: support for PostCSS v5.x - Removed: support for PostCSS v4.x From cba3b6ca7c0fcbc701d005f9ee4cb9d6d09ba086 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Mon, 14 Sep 2015 22:12:21 +0200 Subject: [PATCH 08/25] Fixed: plugin can be consumed correctly from es5 environment (2.0.1) --- CHANGELOG.md | 5 +++++ package.json | 2 +- src/index.js | 16 +++++++++++++--- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0b052d..78fe329 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 2.0.1 - 2015-09-14 + +- Fixed: plugin can be consumed correctly from es5 environment +([#11](https://github.com/cssnext/postcss-cssnext/issues/11)) + # 2.0.0 - 2015-09-14 - Added: support for PostCSS v5.x diff --git a/package.json b/package.json index 36a4722..585926f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "postcss-cssnext", - "version": "2.0.0", + "version": "2.0.1", "description": "Use tomorrow's CSS syntax, today", "keywords": [ "css", diff --git a/src/index.js b/src/index.js index bf8a7d5..79bc9ce 100644 --- a/src/index.js +++ b/src/index.js @@ -4,9 +4,7 @@ import { isSupported } from "caniuse-api" import libraryFeatures from "./features" import featuresActivationMap from "./features-activation-map" -export { libraryFeatures as features } - -export default postcss.plugin("postcss-cssnext", (options) => { +const plugin = postcss.plugin("postcss-cssnext", (options) => { options = { features: {}, // options.browsers is deliberately undefined by default to inherit @@ -68,3 +66,15 @@ export default postcss.plugin("postcss-cssnext", (options) => { return processor }) + +// according to the way babel transpile es6 module +// we cannot use the following syntax to export features +// +// export { libraryFeatures as features } +// +// babel only add `module.exports = exports["default"];` if there is only one +// thing exported +// so we add `features` as a plugin property +plugin.features = libraryFeatures + +export default plugin From ace4a48901f4e13e5eeb7d45744accdd73bdbc33 Mon Sep 17 00:00:00 2001 From: Maksim Koretskiy Date: Tue, 15 Sep 2015 00:35:57 +0300 Subject: [PATCH 09/25] Add postcss-initial --- package.json | 1 + src/__tests__/fixtures/features/initial.css | 14 +++ .../fixtures/features/initial.expected.css | 98 +++++++++++++++++++ src/features.js | 3 + 4 files changed, 116 insertions(+) create mode 100644 src/__tests__/fixtures/features/initial.css create mode 100644 src/__tests__/fixtures/features/initial.expected.css diff --git a/package.json b/package.json index 585926f..f594a1b 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "postcss-custom-properties": "^5.0.0", "postcss-custom-selectors": "^3.0.0", "postcss-font-variant": "^2.0.0", + "postcss-initial": "^1.3.1", "postcss-media-minmax": "^2.1.0", "postcss-pseudo-class-any-link": "^1.0.0", "postcss-pseudoelements": "^3.0.0", diff --git a/src/__tests__/fixtures/features/initial.css b/src/__tests__/fixtures/features/initial.css new file mode 100644 index 0000000..b8cbc54 --- /dev/null +++ b/src/__tests__/fixtures/features/initial.css @@ -0,0 +1,14 @@ +a { + all: initial; +} + +a { + animation: initial; + background: initial; + border: initial; + column-rule: initial; + font: initial; + list-style: initial; + outline: initial; + text-decoration: initial; +} diff --git a/src/__tests__/fixtures/features/initial.expected.css b/src/__tests__/fixtures/features/initial.expected.css new file mode 100644 index 0000000..9ba9c29 --- /dev/null +++ b/src/__tests__/fixtures/features/initial.expected.css @@ -0,0 +1,98 @@ +a { + animation: none 0s ease 0s 1 normal none running; + backface-visibility: visible; + background: transparent none repeat 0 0 / auto auto padding-box border-box scroll; + border: medium none currentColor; + border-collapse: separate; + border-image: none; + border-radius: 0; + border-spacing: 0; + bottom: auto; + box-shadow: none; + box-sizing: content-box; + caption-side: top; + clear: none; + clip: auto; + color: inherit; + columns: auto; + column-count: auto; + column-fill: balance; + column-gap: normal; + column-rule: medium none currentColor; + column-span: 1; + column-width: auto; + content: normal; + counter-increment: none; + counter-reset: none; + cursor: auto; + direction: ltr; + display: inline; + empty-cells: show; + float: none; + font: normal normal normal normal medium/normal inherit; + height: auto; + hyphens: none; + left: auto; + letter-spacing: normal; + list-style: disc outside none; + margin: 0; + max-height: none; + max-width: none; + min-height: 0; + min-width: 0; + opacity: 1; + orphans: 0; + outline: medium none invert; + overflow: visible; + overflow-x: visible; + overflow-y: visible; + padding: 0; + page-break-after: auto; + page-break-before: auto; + page-break-inside: auto; + perspective: none; + perspective-origin: 50% 50%; + position: static; + right: auto; + tab-size: 8; + table-layout: auto; + text-align: inherit; + text-align-last: auto; + text-decoration: none solid currentColor; + text-indent: 0; + text-shadow: none; + text-transform: none; + top: auto; + transform: none; + transform-origin: 50% 50% 0; + transform-style: flat; + transition: none 0s ease 0s; + unicode-bidi: normal; + vertical-align: baseline; + visibility: visible; + white-space: normal; + widows: 0; + width: auto; + word-spacing: normal; + z-index: auto; + all: initial; +} + +a { + animation: none 0s ease 0s 1 normal none running; + animation: initial; + background: transparent none repeat 0 0 / auto auto padding-box border-box scroll; + background: initial; + border: medium none currentColor; + border: initial; + column-rule: medium none currentColor; + column-rule: initial; + font: normal normal normal normal medium/normal inherit; + font: initial; + list-style: disc outside none; + list-style: initial; + outline: medium none invert; + outline: initial; + text-decoration: none solid currentColor; + text-decoration: initial; +} diff --git a/src/features.js b/src/features.js index b2cfe1e..f6892eb 100644 --- a/src/features.js +++ b/src/features.js @@ -36,6 +36,9 @@ export default { filter(options) { return require("pleeease-filters")(options) }, + initial(options) { + return require("postcss-initial")(options) + }, rem(options) { return require("pixrem")(options) }, From c706ef7554a330f0840a5b4a5873b406169a4831 Mon Sep 17 00:00:00 2001 From: Alessandro Zanardi Date: Wed, 16 Sep 2015 13:47:44 +0800 Subject: [PATCH 10/25] Update README.md Closes https://github.com/cssnext/cssnext/pull/215 --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 81e70a4..9438ad1 100644 --- a/README.md +++ b/README.md @@ -17,12 +17,23 @@ It transforms CSS specs into more compatible CSS so you don’t need to wait for ## Why **postcss-cssnext** ? What is the difference with **cssnext** ? +### Short answer + +If you're using PostCSS in your build process, and want to add cssnext, you need only `postcss-cssnext` +(check the "options" section here below). +Otherwise, if you like cssnext to work as a full standalone package with its own cli +(independently of PostCSS), use `cssnext`. + +### More details + cssnext was at first designed to be a complete tool, before PostCSS became popular; thus, includes some options that don't really belong in a PostCSS plugin (e.g., `import`, `url`, `compress`, `plugins`). These days, most people use PostCSS directly so we decided to make integration of cssnext more simple by providing a simple (real) plugin. +### Options + If you were using cssnext with some options here is what you need to know: - `import`: just add into your plugins list From 6ff4925431d8cf6d3e1dd72cccaebbba336443f1 Mon Sep 17 00:00:00 2001 From: Maksim Koretskiy Date: Wed, 16 Sep 2015 11:21:41 +0300 Subject: [PATCH 11/25] Add caniuse keys to activation map --- src/features-activation-map.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/features-activation-map.js b/src/features-activation-map.js index e6f5568..c59da9e 100644 --- a/src/features-activation-map.js +++ b/src/features-activation-map.js @@ -19,6 +19,7 @@ export default { // fontVariant: [ null ], // @todo can be done using a callback, this is only used for Firefox < 35 // filter: [ null ], + initial: [ "css-all", "css-initial-value" ], rem: [ "rem" ], pseudoElements: [ "css-gencontent" ], // pseudoClassMatches: [ null ], From e9b84f866aff01d23e2610dcc85bf350e5fce9f4 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Wed, 16 Sep 2015 22:03:18 +0200 Subject: [PATCH 12/25] 2.1.0 --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78fe329..31c5609 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# 2.1.0 - 2015-09-16 + +- Added: [postcss-initial](https://github.com/maximkoretskiy/postcss-initial) +([#12](https://github.com/cssnext/postcss-cssnext/issues/12)). +Supports `initial` value for all properties. Also it supports `all: initial`. +_Does not support `all: unset` and `all: inherit`._ +Plugin can be useful for creating isolated components. + - `all` specification: https://drafts.csswg.org/css-cascade/#all-shorthand + - `all` browsers support: http://caniuse.com/#feat=css-all + - `initial` value specification: https://drafts.csswg.org/css-cascade/#initial-value + - `initial` value browser support: http://caniuse.com/#feat=css-initial-value + # 2.0.1 - 2015-09-14 - Fixed: plugin can be consumed correctly from es5 environment diff --git a/package.json b/package.json index f594a1b..19fb073 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "postcss-cssnext", - "version": "2.0.1", + "version": "2.1.0", "description": "Use tomorrow's CSS syntax, today", "keywords": [ "css", From 39dddda9d4aca7c3186b0c84747cd519c9e43444 Mon Sep 17 00:00:00 2001 From: Jonathan Neal Date: Wed, 23 Sep 2015 19:10:52 -0400 Subject: [PATCH 13/25] Add PostCSS Nesting --- package.json | 1 + src/__tests__/fixtures/features/nesting.css | 7 +++++++ src/__tests__/fixtures/features/nesting.expected.css | 6 ++++++ src/features.js | 3 +++ 4 files changed, 17 insertions(+) create mode 100644 src/__tests__/fixtures/features/nesting.css create mode 100644 src/__tests__/fixtures/features/nesting.expected.css diff --git a/package.json b/package.json index 19fb073..87cc008 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "postcss-font-variant": "^2.0.0", "postcss-initial": "^1.3.1", "postcss-media-minmax": "^2.1.0", + "postcss-nesting": "^2.0.5", "postcss-pseudo-class-any-link": "^1.0.0", "postcss-pseudoelements": "^3.0.0", "postcss-selector-matches": "^2.0.0", diff --git a/src/__tests__/fixtures/features/nesting.css b/src/__tests__/fixtures/features/nesting.css new file mode 100644 index 0000000..f447c01 --- /dev/null +++ b/src/__tests__/fixtures/features/nesting.css @@ -0,0 +1,7 @@ +.foo { + color: red; + + @nest & .bar { + color: white; + } +} diff --git a/src/__tests__/fixtures/features/nesting.expected.css b/src/__tests__/fixtures/features/nesting.expected.css new file mode 100644 index 0000000..5b82fa2 --- /dev/null +++ b/src/__tests__/fixtures/features/nesting.expected.css @@ -0,0 +1,6 @@ +.foo { + color: red +} +.foo .bar { + color: white +} diff --git a/src/features.js b/src/features.js index f6892eb..5400684 100644 --- a/src/features.js +++ b/src/features.js @@ -6,6 +6,9 @@ export default { calc(options) { return require("postcss-calc")(options) }, + nesting(options) { + return require("postcss-nesting")(options) + }, customMedia(options) { return require("postcss-custom-media")(options) }, From 95f0a641bc744bfe103707d0196d04908918b949 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Tue, 20 Oct 2015 19:40:14 +0200 Subject: [PATCH 14/25] Update README.md --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9438ad1..4eb2042 100644 --- a/README.md +++ b/README.md @@ -53,11 +53,8 @@ If you were using cssnext with some options here is what you need to know: ## But I like cssnext as it was ! -_Don't worry. That's why we created another package._ -The **cssnext** package will have a major release soon in order to introduce a -minor but breaking changes in the Node.js API, but you will get the same tool as -before. -The nice thing is: **cssnext** will use **postcss-cssnext** under the hood. +We plan to offer a simple migration by make postcss better. +Please track this issue https://github.com/cssnext/cssnext/issues/208 --- From c64f384c865d48a4009c49875362ea33774dc113 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Tue, 20 Oct 2015 19:40:41 +0200 Subject: [PATCH 15/25] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4eb2042..7c5a328 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ If you were using cssnext with some options here is what you need to know: ## But I like cssnext as it was ! -We plan to offer a simple migration by make postcss better. +We plan to offer a simple migration by making postcss better. Please track this issue https://github.com/cssnext/cssnext/issues/208 --- From b32b9ead12764d063e019369cfac5e3ae78e52d1 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Wed, 21 Oct 2015 21:22:16 +0200 Subject: [PATCH 16/25] 2.2.0 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31c5609..2ac96b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 2.2.0 - 2015-10-21 + +- Added [postcss-nesting](https://github.com/jonathantneal/postcss-nesting) +([#14](https://github.com/cssnext/postcss-cssnext/issues/14)). +Supports nesting via the `@nest` syntax. See postcss-nesting documentation. + # 2.1.0 - 2015-09-16 - Added: [postcss-initial](https://github.com/maximkoretskiy/postcss-initial) diff --git a/package.json b/package.json index 87cc008..f345516 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "postcss-cssnext", - "version": "2.1.0", + "version": "2.2.0", "description": "Use tomorrow's CSS syntax, today", "keywords": [ "css", From c6a0c91448713e8c2cdf4c829246b7abcb436290 Mon Sep 17 00:00:00 2001 From: Alex Lande Date: Mon, 23 Nov 2015 12:44:55 -0800 Subject: [PATCH 17/25] Update version of pixrem --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f345516..83e1478 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "dependencies": { "autoprefixer": "^6.0.2", "caniuse-api": "^1.3.2", - "pixrem": "^2.0.0", + "pixrem": "^3.0.0", "pleeease-filters": "^2.0.0", "postcss": "^5.0.4", "postcss-calc": "^5.0.0", From 5ff99f6f9b581fda388cc2f96a822ce43b4aaffc Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Wed, 16 Dec 2015 08:22:12 +0100 Subject: [PATCH 18/25] 2.3.0 --- CHANGELOG.md | 12 +++++++++++- package.json | 2 +- .../fixtures/features/autoprefixer.expected.css | 4 +++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ac96b4..cecf166 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ +# 2.3.0 - 2015-12-16 + +- Added: we use latest version of pixrem(@^3) +([19](https://github.com/cssnext/postcss-cssnext/pull/19)) +So now `rem` have +[2 new parameters](https://github.com/robwierzbowski/node-pixrem#options): + - ``rootValue`` to define the root element font-size manually + - ``unitPrecision`` for rounded values + + # 2.2.0 - 2015-10-21 -- Added [postcss-nesting](https://github.com/jonathantneal/postcss-nesting) +- Added: [postcss-nesting](https://github.com/jonathantneal/postcss-nesting) ([#14](https://github.com/cssnext/postcss-cssnext/issues/14)). Supports nesting via the `@nest` syntax. See postcss-nesting documentation. diff --git a/package.json b/package.json index 83e1478..463ca95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "postcss-cssnext", - "version": "2.2.0", + "version": "2.3.0", "description": "Use tomorrow's CSS syntax, today", "keywords": [ "css", diff --git a/src/__tests__/fixtures/features/autoprefixer.expected.css b/src/__tests__/fixtures/features/autoprefixer.expected.css index 175ed52..76c0fd9 100644 --- a/src/__tests__/fixtures/features/autoprefixer.expected.css +++ b/src/__tests__/fixtures/features/autoprefixer.expected.css @@ -1,6 +1,8 @@ * { -webkit-transition: -webkit-transform 1s; - transition: transform 1s; + transition: -webkit-transform 1s; + transition: transform 1s; + transition: transform 1s, -webkit-transform 1s; } @-webkit-keyframes spin { From b9076ee7ba00dd343918102ac3f2a37c6f16a80a Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Tue, 29 Dec 2015 06:36:26 +0100 Subject: [PATCH 19/25] Fix linting issues related to postcss-cssnext merge --- .eslintrc | 2 +- docs/scripts/build.js | 10 +++++----- docs/scripts/webpack.js | 10 ++++++++-- docs/src/layouts/Default.js | 4 ++-- docs/src/layouts/Simple.js | 4 ++-- docs/src/modules/Analytics/index.js | 2 +- docs/src/modules/Body/index.js | 2 +- docs/src/modules/Footer/index.js | 2 +- docs/src/modules/Head/index.js | 2 +- docs/src/modules/Header/index.js | 2 +- docs/src/modules/Header/link.js | 4 ++-- docs/src/modules/Html/index.js | 2 +- docs/src/modules/SVGIcon/__tests__/index.js | 4 ++-- docs/src/modules/SVGIcon/index.js | 21 ++++++++++++--------- docs/src/modules/playground/index.js | 2 +- docs/src/modules/requireRaw.js | 2 +- webpack.config.js | 2 +- 17 files changed, 43 insertions(+), 34 deletions(-) diff --git a/.eslintrc b/.eslintrc index a7d1082..440906a 100644 --- a/.eslintrc +++ b/.eslintrc @@ -35,6 +35,7 @@ rules: indent: [2, 2] # 2 spaces indentation max-len: [2, 80, 4] quotes: [2, "double"] + jsx-quotes: [2, "prefer-double"] semi: [2, "never"] no-multiple-empty-lines: [2, {"max": 1}] @@ -65,7 +66,6 @@ rules: # eslint-plugin-react rules react/jsx-boolean-value: 2 react/jsx-no-undef: 2 - react/jsx-quotes: 2 #react/jsx-sort-prop-types: 2 #react/jsx-sort-props: 2 react/jsx-uses-react: 2 diff --git a/docs/scripts/build.js b/docs/scripts/build.js index 1d89d75..bb56245 100644 --- a/docs/scripts/build.js +++ b/docs/scripts/build.js @@ -1,6 +1,6 @@ import path from "path" -import {sync as rm} from "rimraf" +import { sync as rm } from "rimraf" import color from "chalk" import Metalsmith from "metalsmith" @@ -30,7 +30,7 @@ const log = nanoLogger("./build") JSON.stringify(buildConfig, null, 2).split("\n").forEach(l => log(l)) -const mdToHtmlReplacement = [/\.md$/, ".html"] +const mdToHtmlReplacement = [ /\.md$/, ".html" ] // We clean ./dist by hand mainly for prod, in order to be able to build // assets with webpack before metalsmith build. @@ -63,7 +63,7 @@ smith .use( url([ mdToHtmlReplacement, - [/index\.html?$/, ""], + [ /index\.html?$/, "" ], ]) ) // wrap .html into react `template:` @@ -87,9 +87,9 @@ smith rename([ mdToHtmlReplacement, // no .html at the end of urls - [/\.html$/, "/index.html"], + [ /\.html$/, "/index.html" ], // ensure we only have index.html, no index/index - [/index\/index\.html$/, "index.html"], + [ /index\/index\.html$/, "index.html" ], ]) ) diff --git a/docs/scripts/webpack.js b/docs/scripts/webpack.js index 43e59ba..9de629e 100644 --- a/docs/scripts/webpack.js +++ b/docs/scripts/webpack.js @@ -9,13 +9,19 @@ export default (webpackConfig, log, cb) => { if (stats.hasErrors()) { stats.compilation.errors.forEach( - item => log(...[color.red("Error:"), ...item.message.split("\n")]) + item => log(...[ + color.red("Error:"), + ...item.message.split("\n"), + ]) ) throw new Error("webpack build failed with errors") } if (stats.hasWarnings()) { stats.compilation.warnings.forEach( - item => log(...[color.yellow("Warning:"), ...item.message.split("\n")]) + item => log(...[ + color.yellow("Warning:"), + ...item.message.split("\n"), + ]) ) } diff --git a/docs/src/layouts/Default.js b/docs/src/layouts/Default.js index 6104261..788b55b 100644 --- a/docs/src/layouts/Default.js +++ b/docs/src/layouts/Default.js @@ -1,4 +1,4 @@ -import React, {Component, PropTypes} from "react" +import React, { Component, PropTypes } from "react" import cx from "classnames" import dashify from "../modules/dashify" @@ -124,7 +124,7 @@ export default class Default extends Component { "r-Grid-cell": true, "js-markdownIt-TOCOriginalContainer": true, })} - dangerouslySetInnerHTML={{__html: file.contents}} + dangerouslySetInnerHTML={{ __html: file.contents }} />
diff --git a/docs/src/modules/Analytics/index.js b/docs/src/modules/Analytics/index.js index 73bdee8..ef14cef 100644 --- a/docs/src/modules/Analytics/index.js +++ b/docs/src/modules/Analytics/index.js @@ -1,4 +1,4 @@ -import React, {Component} from "react" +import React, { Component } from "react" import isogram from "isogram" diff --git a/docs/src/modules/Body/index.js b/docs/src/modules/Body/index.js index 0c21ee9..95f2e30 100644 --- a/docs/src/modules/Body/index.js +++ b/docs/src/modules/Body/index.js @@ -1,4 +1,4 @@ -import React, {Component, PropTypes} from "react" +import React, { Component, PropTypes } from "react" import Header from "../Header" import Footer from "../Footer" diff --git a/docs/src/modules/Footer/index.js b/docs/src/modules/Footer/index.js index 4f477be..ce4aa80 100644 --- a/docs/src/modules/Footer/index.js +++ b/docs/src/modules/Footer/index.js @@ -1,4 +1,4 @@ -import React, {Component, PropTypes} from "react" +import React, { Component, PropTypes } from "react" import SVGIcon from "../SVGIcon" import requireRaw from "../requireRaw" diff --git a/docs/src/modules/Head/index.js b/docs/src/modules/Head/index.js index 8b6464b..4c74efe 100644 --- a/docs/src/modules/Head/index.js +++ b/docs/src/modules/Head/index.js @@ -1,4 +1,4 @@ -import React, {Component, PropTypes} from "react" +import React, { Component, PropTypes } from "react" export default class Head extends Component { diff --git a/docs/src/modules/Header/index.js b/docs/src/modules/Header/index.js index 7df2d7a..f9b47f3 100644 --- a/docs/src/modules/Header/index.js +++ b/docs/src/modules/Header/index.js @@ -1,4 +1,4 @@ -import React, {Component, PropTypes} from "react" +import React, { Component, PropTypes } from "react" import SVGIcon from "../SVGIcon" import requireRaw from "../requireRaw" diff --git a/docs/src/modules/Header/link.js b/docs/src/modules/Header/link.js index 5fe4532..a495f6c 100644 --- a/docs/src/modules/Header/link.js +++ b/docs/src/modules/Header/link.js @@ -1,4 +1,4 @@ -import React, {Component, PropTypes} from "react" +import React, { Component, PropTypes } from "react" import cx from "classnames" export default class HeaderLink extends Component { @@ -30,7 +30,7 @@ export default class HeaderLink extends Component { className={cx({ ...( this.props.className - ? {[this.props.className]: true} + ? { [this.props.className]: true } : {} ), "cssnext-Header-nav-item": true, diff --git a/docs/src/modules/Html/index.js b/docs/src/modules/Html/index.js index 586763b..4b56e75 100644 --- a/docs/src/modules/Html/index.js +++ b/docs/src/modules/Html/index.js @@ -1,4 +1,4 @@ -import React, {Component, PropTypes} from "react" +import React, { Component, PropTypes } from "react" export default class Html extends Component { diff --git a/docs/src/modules/SVGIcon/__tests__/index.js b/docs/src/modules/SVGIcon/__tests__/index.js index 44815f1..eedebab 100644 --- a/docs/src/modules/SVGIcon/__tests__/index.js +++ b/docs/src/modules/SVGIcon/__tests__/index.js @@ -1,5 +1,5 @@ import tape from "tape-catch" -import React, {Component} from "react" +import React, { Component } from "react" import SVGIcon from ".." tape("SVGIcon", (test) => { @@ -70,7 +70,7 @@ tape("SVGIcon", (test) => { test.equal( React.renderToStaticMarkup( - + ), `${SVGIconCleanedStart}>` + ``, diff --git a/docs/src/modules/SVGIcon/index.js b/docs/src/modules/SVGIcon/index.js index ec2e41c..0a062e5 100644 --- a/docs/src/modules/SVGIcon/index.js +++ b/docs/src/modules/SVGIcon/index.js @@ -1,4 +1,4 @@ -import React, {Component, PropTypes} from "react" +import React, { Component, PropTypes } from "react" // import styled from "bloody-react-styled" import cx from "classnames" @@ -28,14 +28,9 @@ const cleanups = { // @styled(styles) export default class SVGIcon extends Component { - static defaultProps = { - component: "span", - classSuffix: "-svg", - cleanup: [], - cleanupExceptions: [], - } - static propTypes = { + className: PropTypes.string, + classSuffix: PropTypes.string, component: PropTypes.oneOfType([ PropTypes.string, PropTypes.func, @@ -46,10 +41,18 @@ export default class SVGIcon extends Component { PropTypes.bool, PropTypes.array, ]), + cleanupExceptions: PropTypes.array, width: PropTypes.string, height: PropTypes.string, } + static defaultProps = { + component: "span", + classSuffix: "-svg", + cleanup: [], + cleanupExceptions: [], + } + static cleanupSvg(svg, cleanup = []) { return Object.keys(cleanups) .filter(key => cleanup.includes(key)) @@ -97,7 +100,7 @@ export default class SVGIcon extends Component { height = width } - const props = {...this.props} + const props = { ...this.props } // remove useless props for wrapper delete props.svg delete props.fill diff --git a/docs/src/modules/playground/index.js b/docs/src/modules/playground/index.js index ad0c60e..edb5d6c 100644 --- a/docs/src/modules/playground/index.js +++ b/docs/src/modules/playground/index.js @@ -1,5 +1,5 @@ import cssnext from "../../../../src/index" -import {version as cssnextVersion} from "../../../../package" +import { version as cssnextVersion } from "../../../../package" import messagesStyles from "../../../../src/option.messages.browser.styles" const bullet = "›" diff --git a/docs/src/modules/requireRaw.js b/docs/src/modules/requireRaw.js index 7fe4aec..85826e5 100644 --- a/docs/src/modules/requireRaw.js +++ b/docs/src/modules/requireRaw.js @@ -11,7 +11,7 @@ if (fs && fs.readFileSync) { requireRaw = (filename) => { return fs.readFileSync( path.join(__dirname, "..", "..", filename), - {encoding: "utf8"} + { encoding: "utf8" } ) } } diff --git a/webpack.config.js b/webpack.config.js index 289e869..249cf29 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -48,7 +48,7 @@ module.exports = { plugins: ([ new webpack.DefinePlugin(buildConfig), - new ExtractTextPlugin("[name].css", {disable: !buildConfig.__PROD__}), + new ExtractTextPlugin("[name].css", { disable: !buildConfig.__PROD__ }), ].concat( buildConfig.__PROD__ ? [ From 1f4e5700763fc6db900785126a45b20b652e1d7e Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Tue, 29 Dec 2015 06:47:06 +0100 Subject: [PATCH 20/25] Remove unused microtime dep Closes #218 #219 --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 463ca95..12781d2 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,6 @@ "metalsmith-rss": "^1.0.0", "metalsmith-url": "^1.0.0", "metalsmith-watch": "^1.0.1", - "microtime": "^1.2.0", "nano-logger": "^1.0.0", "node-libs-browser": "^0.5.0", "normalize.css": "^3.0.3", From ddec35c1f96cd4c17e921100525ac047a5843096 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Tue, 29 Dec 2015 06:56:22 +0100 Subject: [PATCH 21/25] Fix playground --- docs/src/modules/playground/index.js | 2 +- .../src/modules/playground/messages.styles.js | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 docs/src/modules/playground/messages.styles.js diff --git a/docs/src/modules/playground/index.js b/docs/src/modules/playground/index.js index edb5d6c..7748522 100644 --- a/docs/src/modules/playground/index.js +++ b/docs/src/modules/playground/index.js @@ -1,6 +1,6 @@ import cssnext from "../../../../src/index" import { version as cssnextVersion } from "../../../../package" -import messagesStyles from "../../../../src/option.messages.browser.styles" +import messagesStyles from "./messages.styles" const bullet = "›" diff --git a/docs/src/modules/playground/messages.styles.js b/docs/src/modules/playground/messages.styles.js new file mode 100644 index 0000000..a5e0876 --- /dev/null +++ b/docs/src/modules/playground/messages.styles.js @@ -0,0 +1,50 @@ +/* eslint-disable max-len */ +// source: http://iconmonstr.com/warning-3-icon/ +const svgGradient = ` + + + + +` +const warningSVG = ` + + ${ svgGradient } + + +`.trim() +/* eslint-enable max-len */ + +export default { + display: "block", + "white-space": "pre-wrap", + + // not a problem for old browsers, box will still be on top of body + position: "fixed", + top: 0, + left: 0, + right: 0, + "z-index": 10000, // just in case you know + + "font-size": ".9em", + padding: "1.5em 1em 1.5em 4.5em", // padding + background image padding + + color: "#318edf", + "background-color": "#fff", + + background: ( + `url( + "data:image/svg+xml;charset=utf-8,${encodeURIComponent(warningSVG)}" + ) 1em 1em / 2.5em 2.5em no-repeat, #fff` + ), + + // sugar + "border-bottom": "4px solid #318edf", + "box-shadow": "0 0 .6em rgba(0,0,0, .25)", + + // nice font + "font-family": "Menlo, Monaco, monospace", +} From 84faf94e837814851ef30b4b2c75518b031e53f9 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Tue, 29 Dec 2015 06:58:15 +0100 Subject: [PATCH 22/25] =?UTF-8?q?``tomorrow=E2=80=99``=20instead=20of=20``?= =?UTF-8?q?tomorrow'``?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #235 --- README.md | 2 +- docs/content/index.md | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7c5a328..28da698 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Join the chat at https://gitter.im/cssnext/cssnext](https://img.shields.io/badge/gitter%20-join%20chat%20%E2%9E%9E-1dce73.svg)](https://gitter.im/cssnext/cssnext) -> Use tomorrow's CSS syntax, today. +> Use tomorrow’s CSS syntax, today. cssnext is a CSS transpiler that allows you to use the latest CSS syntax today. It transforms CSS specs into more compatible CSS so you don’t need to wait for browser support. diff --git a/docs/content/index.md b/docs/content/index.md index c0140d6..f52fd86 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -1,11 +1,11 @@ --- template: Simple -title: cssnext - Use tomorrow's CSS syntax, today. +title: cssnext - Use tomorrow’s CSS syntax, today. ---
- Use tomorrow's CSS syntax, today. + Use tomorrow’s CSS syntax, today.

Date: Tue, 29 Dec 2015 09:31:55 +0100 Subject: [PATCH 23/25] cssnext -> postcss-cssnext --- CHANGELOG.md | 58 +++++----- README.md | 56 +--------- docs/content/features.md | 23 +--- docs/content/index.md | 57 ++-------- docs/content/postcss.md | 159 +++++++++++++++++++++++++++ docs/content/setup.md | 145 ++++-------------------- docs/content/usage.md | 150 +------------------------ docs/src/assets/flux.jpg | Bin 90431 -> 0 bytes docs/src/index.css | 21 +--- docs/src/layouts/Default.js | 6 +- docs/src/modules/Footer/index.js | 4 +- docs/src/modules/Header/index.js | 7 +- docs/src/modules/playground/index.js | 3 +- package.json | 12 +- 14 files changed, 250 insertions(+), 451 deletions(-) create mode 100644 docs/content/postcss.md delete mode 100644 docs/src/assets/flux.jpg diff --git a/CHANGELOG.md b/CHANGELOG.md index cecf166..265f560 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,23 +1,22 @@ # 2.3.0 - 2015-12-16 - Added: we use latest version of pixrem(@^3) -([19](https://github.com/cssnext/postcss-cssnext/pull/19)) +([6d44410](https://github.com/MoOx/postcss-cssnext/commit/6d4441023f30895211f010776b142d02359f4d0a)) So now `rem` have [2 new parameters](https://github.com/robwierzbowski/node-pixrem#options): - ``rootValue`` to define the root element font-size manually - ``unitPrecision`` for rounded values - # 2.2.0 - 2015-10-21 - Added: [postcss-nesting](https://github.com/jonathantneal/postcss-nesting) -([#14](https://github.com/cssnext/postcss-cssnext/issues/14)). +([b31f167](https://github.com/MoOx/postcss-cssnext/commit/b31f167d7659a18a14fce65a7a94da07560e6a59)). Supports nesting via the `@nest` syntax. See postcss-nesting documentation. # 2.1.0 - 2015-09-16 - Added: [postcss-initial](https://github.com/maximkoretskiy/postcss-initial) -([#12](https://github.com/cssnext/postcss-cssnext/issues/12)). +([a907881](https://github.com/MoOx/postcss-cssnext/commit/a90788153801a3f898f6cc1ade189d4de2af3367)). Supports `initial` value for all properties. Also it supports `all: initial`. _Does not support `all: unset` and `all: inherit`._ Plugin can be useful for creating isolated components. @@ -29,17 +28,20 @@ Plugin can be useful for creating isolated components. # 2.0.1 - 2015-09-14 - Fixed: plugin can be consumed correctly from es5 environment -([#11](https://github.com/cssnext/postcss-cssnext/issues/11)) +([7d6d3c0](https://github.com/MoOx/postcss-cssnext/commit/7d6d3c018d8ca17091d4cfe3d5d61e246ad8775d)). # 2.0.0 - 2015-09-14 - Added: support for PostCSS v5.x - Removed: support for PostCSS v4.x +([b5ece99...8907c13](https://github.com/MoOx/postcss-cssnext/compare/b5ece99c1e1b5e4cdfd6c25f856946bbcbc2247c...8907c13d31662a2cb393edb0387144dfbba81659)). --- **pre 2.0.0 information was related to `cssnext` package.** +--- + # 1.8.4 - 2015-08-24 - Fixed: `compress` option now works again correctly. A recent update in cssnano @@ -47,7 +49,7 @@ has introduced some minor breaking changes the way cssnext changed plugins metadata (`pluginName`). A direct minor change is that `messages` (in console or in css output) now show real origin (postcss plugin name) instead of a vague "cssnext" origin. -([#195](https://github.com/cssnext/cssnext/issues/195)) +([#195](https://github.com/MoOx/postcss-cssnext/issues/195)) # 1.8.3 - 2015-08-06 @@ -57,28 +59,28 @@ severals fixes. # 1.8.2 - 2015-07-23 - Fixed: CLI watcher now works watchs correctl multiples `@import` -([#123](https://github.com/cssnext/cssnext/issues/123)) +([#123](https://github.com/MoOx/postcss-cssnext/issues/123)) # 1.8.1 - 2015-07-15 - Added: cssnext now throw an error if used as a webpack loader to prevent unexpected usage with a recommendation for -[cssnext-loader](https://github.com/cssnext/cssnext-loader) -([#61](https://github.com/cssnext/cssnext/issues/61)) +[cssnext-loader](https://github.com/MoOx/postcss-cssnext-loader) +([#61](https://github.com/MoOx/postcss-cssnext/issues/61)) # 1.8.0 - 2015-06-29 - Fixed: replacement of `postcss-log-warnings` (deprecated) by `postcss-reporter` -([#162](https://github.com/cssnext/cssnext/issues/162)) +([#162](https://github.com/MoOx/postcss-cssnext/issues/162)) - Fixed: CLI now add `to` option automatically -([#159](https://github.com/cssnext/cssnext/issues/159)) +([#159](https://github.com/MoOx/postcss-cssnext/issues/159)) If you were happy with the previous CLI behavior (which was not rebasing url), you should probably just add the `--no-url` to keep the CSS as it was. - Changed: `compress` option now use cssnano v2.x -([#166](https://github.com/cssnext/cssnext/issues/166)) +([#166](https://github.com/MoOx/postcss-cssnext/issues/166)) - Added: CLI output file dirname is now automatically created (using `mkdirp`) -([#146](https://github.com/cssnext/cssnext/issues/146)) +([#146](https://github.com/MoOx/postcss-cssnext/issues/146)) # 1.7.1 - 2015-06-19 @@ -94,28 +96,28 @@ Now you must use `@custom-selector :--{name}` syntax instead of `@custom-selector --{name}` The support of syntax without : and the warning message will be remove in the next major release -([#97](https://github.com/cssnext/cssnext/issues/97)) +([#97](https://github.com/MoOx/postcss-cssnext/issues/97)) - Added: `plugins` option that allows you to pipe your own transformations -([#118](https://github.com/cssnext/cssnext/issues/118)) +([#118](https://github.com/MoOx/postcss-cssnext/issues/118)) - Added: `messages` option that allows you to see messages of transformations -([#88](https://github.com/cssnext/cssnext/issues/88)) +([#88](https://github.com/MoOx/postcss-cssnext/issues/88)) - Added: `:any-link` pseudo class support # 1.6.0 - 2015-06-02 - Added: prevent mutability issues with frozen options objects -([#147](https://github.com/cssnext/cssnext/pull/147)) +([#147](https://github.com/MoOx/postcss-cssnext/pull/147)) # 1.5.2 - 2015-05-27 - Fixed: support for autoprefixer 5.2 -([#131](https://github.com/cssnext/cssnext/issues/131)) +([#131](https://github.com/MoOx/postcss-cssnext/issues/131)) # 1.5.1 - 2015-05-25 - Fixed: when printing a bug report in CLI, url was not printed, due to a replacement of colors lib by chalk in 1.5.0 -([#129](https://github.com/cssnext/cssnext/pull/129)) +([#129](https://github.com/MoOx/postcss-cssnext/pull/129)) # 1.5.0 - 2015-05-23 @@ -163,7 +165,7 @@ files anymore # 1.0.1 - 2015-02-18 - Fixed: cssnext binary doesn't exit on an error if --watch is enabled -([#69](https://github.com/cssnext/cssnext/pull/69)) +([#69](https://github.com/MoOx/postcss-cssnext/pull/69)) # 1.0.0 - 2015-02-06 @@ -204,7 +206,7 @@ autoprefixer # 0.6.6 - 2014-12-22 - Fixed: `Cannot find module 'exit'` error when an error came out -([#54](https://github.com/cssnext/cssnext/issues/54)) +([#54](https://github.com/MoOx/postcss-cssnext/issues/54)) # 0.6.5 - 2014-12-16 @@ -258,7 +260,7 @@ v3.0.0 have by default `{inline: true, sourceContent: true}` # 0.4.3 - 2014-11-09 - Added: font-variant support -([#42](https://github.com/cssnext/cssnext/issues/42)) +([#42](https://github.com/MoOx/postcss-cssnext/issues/42)) # 0.4.2 - 2014-11-02 @@ -267,17 +269,17 @@ v3.0.0 have by default `{inline: true, sourceContent: true}` - Added: echo a warning when using a non root custom properties ([#13](https://github.com/postcss/postcss-custom-properties/issues/13)) - Added: cssnext can return a postcss instance of no string given -([#3](https://github.com/cssnext/cssnext/issues/3)) +([#3](https://github.com/MoOx/postcss-cssnext/issues/3)) # 0.4.1 - 2014-11-01 - Added: gray() support -([#44](https://github.com/cssnext/cssnext/issues/44)) +([#44](https://github.com/MoOx/postcss-cssnext/issues/44)) # 0.4.0 - 2014-10-23 - Changed: color feature has been exploded to multiples features -([#40](https://github.com/cssnext/cssnext/issues/40)). +([#40](https://github.com/MoOx/postcss-cssnext/issues/40)). Before @@ -313,7 +315,7 @@ var output = cssnext(input, { - Changed: cssnext options are not passed to all plugins anymore. You know need to specify feature options by passing object to `features` properties -([#39](https://github.com/cssnext/cssnext/issues/39)). +([#39](https://github.com/MoOx/postcss-cssnext/issues/39)). Before @@ -348,7 +350,7 @@ This change have been made to avoid collision between options # 0.3.1 - 2014-08-27 - Fixed: nested custom properties usages -([#25](https://github.com/cssnext/cssnext/issues/25)) +([#25](https://github.com/MoOx/postcss-cssnext/issues/25)) # 0.3.0 - 2014-08-26 @@ -358,7 +360,7 @@ This change have been made to avoid collision between options # 0.2.3 - 2014-08-26 - Fixed: support empty files -([#24](https://github.com/cssnext/cssnext/issues/24)) +([#24](https://github.com/MoOx/postcss-cssnext/issues/24)) # 0.2.2 - 2014-08-22 diff --git a/README.md b/README.md index 28da698..701831e 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,32 @@ # postcss-cssnext [![NPM version](http://img.shields.io/npm/v/postcss-cssnext.svg?style=flat)](https://www.npmjs.org/package/postcss-cssnext) -[![Travis Build Status](https://img.shields.io/travis/cssnext/postcss-cssnext.svg?label=unix%20build)](https://travis-ci.org/cssnext/postcss-cssnext) +[![Travis Build Status](https://img.shields.io/travis/MoOx/postcss-cssnext.svg?label=unix%20build)](https://travis-ci.org/cssnext/postcss-cssnext) [![AppVeyor Build Status](https://img.shields.io/appveyor/ci/MoOx/postcss-cssnext.svg?label=windows%20build)](https://ci.appveyor.com/project/MoOx/postcss-cssnext) -[![Join the chat at https://gitter.im/cssnext/cssnext](https://img.shields.io/badge/gitter%20-join%20chat%20%E2%9E%9E-1dce73.svg)](https://gitter.im/cssnext/cssnext) +[![Join the chat at https://gitter.im/MoOx/postcss-cssnext](https://img.shields.io/badge/gitter%20-join%20chat%20%E2%9E%9E-1dce73.svg)](https://gitter.im/MoOx/postcss-cssnext) > Use tomorrow’s CSS syntax, today. -cssnext is a CSS transpiler that allows you to use the latest CSS syntax today. +PostCSS-cssnext is a PostCSS plugin that helps you to use the latest CSS syntax today. It transforms CSS specs into more compatible CSS so you don’t need to wait for browser support. --- -# This repository contains the PostCSS plugin. - -## Why **postcss-cssnext** ? What is the difference with **cssnext** ? - -### Short answer - -If you're using PostCSS in your build process, and want to add cssnext, you need only `postcss-cssnext` -(check the "options" section here below). -Otherwise, if you like cssnext to work as a full standalone package with its own cli -(independently of PostCSS), use `cssnext`. - -### More details - -cssnext was at first designed to be a complete tool, before PostCSS became -popular; thus, includes some options that don't really belong in a PostCSS -plugin (e.g., `import`, `url`, `compress`, `plugins`). -These days, most people use PostCSS directly so we decided to make integration of -cssnext more simple by providing a simple (real) plugin. - -### Options - -If you were using cssnext with some options here is what you need to know: - -- `import`: just add into your plugins list - [`postcss-import`](https://github.com/postcss/postcss-import) -- `url`: just add into your plugins list - [`postcss-url`](https://github.com/postcss/postcss-url) -- `compress`: just add into your plugins list - [`cssnano`](https://github.com/ben-eb/cssnano) -- `plugins`: just add the plugins directly in your list -- `messages`: see - [`postcss-reporter`](https://github.com/postcss/postcss-reporter) - and - [`postcss-browser-reporter`](https://github.com/postcss/postcss-browser-reporter) -- `sourcemap`, `map`, `to`, `from`: see - [PostCSS source map documentation](https://github.com/postcss/postcss#source-map) - - -## But I like cssnext as it was ! - -We plan to offer a simple migration by making postcss better. -Please track this issue https://github.com/cssnext/cssnext/issues/208 - ---- - ## Check out [cssnext website](http://cssnext.io/) - [Features](http://cssnext.io/features/) - [Setup](http://cssnext.io/setup/) - [Usage](http://cssnext.io/usage/) - [Playground](http://cssnext.io/playground/) +- [Migration to postcss-cssnext](http://cssnext.io/postcss/) For questions and support please visit the -[gitter room](https://gitter.im/cssnext/cssnext). +[gitter room](https://gitter.im/MoOx/postcss-cssnext). --- -_The [issue tracker](https://github.com/cssnext/cssnext/issues) is exclusively for bug reports and feature requests._ +_The [issue tracker](https://github.com/MoOx/postcss-cssnext/issues) is exclusively for bug reports and feature requests._ --- diff --git a/docs/content/features.md b/docs/content/features.md index 68125bc..7e1d000 100644 --- a/docs/content/features.md +++ b/docs/content/features.md @@ -1,5 +1,5 @@ --- -title: cssnext features +title: postcss-cssnext features subtitle: Discover the future of CSS backgroundModifier: darkRoad @@ -337,30 +337,13 @@ body { _Note that according to your [browser scope](#nodejs-options) some might be not transpiled to avoid extra useless output._ -## Bonus features - -_The features below are considered as bonus since it's totally not -related to CSS specs._ - -### `@import` - -`@import` inline local files and modules - `node_modules` or `web_modules` -([⇗](https://github.com/postcss/postcss-import)) to output a bundled CSS file. -`url()` referenced are also rebased. - -### minification - -minification/compression is available ([⇗](https://github.com/ben-eb/cssnano)) -if you want to compress the output for production. - - ## @todo Any omissions of the CSS specifications (even in draft) that are subject to be handled by cssnext are not intentional. -You can take a look at the [list of features that are waiting to be implemented](https://github.com/cssnext/cssnext/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+feature+request%22). +You can take a look at the [list of features that are waiting to be implemented](https://github.com/MoOx/postcss-cssnext/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+feature+request%22). Feel free to work on a feature ready to be added, or -[open a new issue](https://github.com/cssnext/cssnext/issues/new) +[open a new issue](https://github.com/MoOx/postcss-cssnext/issues/new) if you find something that should be handled. Keep in mind that, as of right now, this project is intended to support new CSS *syntax* only. diff --git a/docs/content/index.md b/docs/content/index.md index f52fd86..46c5e2d 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -8,10 +8,10 @@ title: cssnext - Use tomorrow’s CSS syntax, today. Use tomorrow’s CSS syntax, today.

- Check out cssnext on GitHub + Check out postcss-cssnext on GitHub or @@ -22,7 +22,7 @@ title: cssnext - Use tomorrow’s CSS syntax, today. frameborder="0" scrolling="0" width="145px" height="30px" style="vertical-align: middle" - src="https://ghbtns.com/github-btn.html?user=cssnext&repo=cssnext&type=star&count=true&size=large" + src="https://ghbtns.com/github-btn.html?user=MoOx&repo=postcss-cssnext&type=star&count=true&size=large" >

@@ -32,8 +32,8 @@ title: cssnext - Use tomorrow’s CSS syntax, today.

What is cssnext?

- cssnext is a CSS transpiler that allows you to use - the latest CSS syntax today. + PostCSS-cssnext is a PostCSS + plugin that helps you to use the latest CSS syntax today. It transforms new CSS specs into more compatible CSS @@ -168,52 +168,11 @@ title: cssnext - Use tomorrow’s CSS syntax, today.

-
-
-
-

Active development

-

- No longer wait for releases. - A fixed bug will be released ASAP. -
- Minor features will never be idle for long. -
- See that by yourself on - cssnext - & - PostCSS. - activities graphs. -
- cssnext uses lots of PostCSS plugins, - so check them out too. -

-
-
-
- -
-
-
-
-

Based on NPM ecosystem

-

- cssnext uses npm packages that should respect semver. -
- Bugfixes are pushed often. - Minor changes won't break your code. - Major releases are, well, major and are not supposed to happen a lot. -
- Codebase is exploded into smart and standalone packages so it's easier to work on something or fix a bug. -

-
-
-
-
@@ -226,7 +185,7 @@ title: cssnext - Use tomorrow’s CSS syntax, today. @cssnext to get the latest news or - join the chat on gitter + join the chat on gitter if you have any questions.
diff --git a/docs/content/postcss.md b/docs/content/postcss.md new file mode 100644 index 0000000..98a4fbc --- /dev/null +++ b/docs/content/postcss.md @@ -0,0 +1,159 @@ +--- +title: Using postcss-cssnext +subtitle: How to migrate from cssnext to postcss-cssnext +--- + +## Why **postcss-cssnext**? What is the difference with **cssnext**? + +### Short answer: PostCSS + +If you're using [PostCSS](https://github.com/postcss/postcss) +in your build process, and were using `cssnext`, +you can quickly switch to only `postcss-cssnext` +(check the [Migration](#migration) section here below). + +### Wait? What is PostCSS? + +cssnext was at first designed to be a complete tool, before PostCSS became +popular; thus, includes some options that don't really belong in a PostCSS +plugin focused on the future of CSS +(e.g., `import`, `url`, `compress`, `plugins`...) . + +These days, most people use [PostCSS](https://github.com/postcss/postcss) +directly (so they can easily adjust and choose their CSS transformations) +so we decided to make integration and of cssnext more simple by providing a +simple (real) plugin. + +Also, having to maintain severals cssnext and PostCSS runners that does almost +the same is not optimal. + +### Migration + +If you were using cssnext with some options here is what you need to know: + +#### Options + +##### Options `import`, `url`, `compress`, `messages` + +- `import` options is just + [`postcss-import`](https://github.com/postcss/postcss-import) +- `url` option is just + [`postcss-url`](https://github.com/postcss/postcss-url) +- `compress` option is just + [`cssnano`](https://github.com/ben-eb/cssnano) +- `messages`: was a combination of + [`postcss-reporter`](https://github.com/postcss/postcss-reporter) + and + [`postcss-browser-reporter`](https://github.com/postcss/postcss-browser-reporter). + Just pick up the one you want (or both). + +##### Option `plugins` + +Just add the plugins directly in your PostCSS list. + +##### Options `sourcemap`, `map`, `to`, `from` + +These options were just proxy to [PostCSS source map options](https://github.com/postcss/postcss/blob/master/docs/source-maps.md). + +#### Examples + +If you were using cssnext with default options, you might just need this: + +```console +$ npm uninstall cssnext [--save[-dev]] +$ npm install postcss postcss-import postcss-url postcss-reporter postcss-browser-reporter postcss-cssnext [--save[-dev]] +``` + +With the previous lines you might thing that you are going backward by having a +more complex boilerplate. But if you look carefully, you will notice that you +might not be interested by some options. + +Now that you have the appropriate plugins, here are some examples with some runners +and previous default cssnext behavior. + +##### [postcss-cli](https://www.npmjs.com/package/postcss-cli) + +Here is an example of the json config you might use with something like +``$ postcss-cli -c postcss.config.json``. + +```json +{ + "use": [ + "postcss-import", + "postcss-url", + "postcss-cssnext" + "postcss-browser-reporter", + "postcss-reporter", + ] +} +``` + +##### [grunt-postcss](https://www.npmjs.com/package/grunt-postcss) + +```js +grunt.initConfig({ + postcss: { + options: { + processors: [ + require("postcss-import")(), + require("postcss-url")(), + require("postcss-cssnext")(), + require("postcss-browser-reporter")(), + require("postcss-reporter")(), + ] + }, + dist: { + src: 'css/*.css' + } + } +}); +``` + +##### [gulp-postcss](https://www.npmjs.com/package/gulp-postcss) + +```js +var gulp = require('gulp') +var postcss = require('gulp-postcss') + +gulp.task('css', function () { + return ( + gulp.src('./src/*.css') + .pipe(postcss([ + require("postcss-import")(), + require("postcss-url")(), + require("postcss-cssnext")(), + require("postcss-browser-reporter")(), + require("postcss-reporter")(), + ])) + .pipe(gulp.dest('./dest')) + ) +}) +``` + +##### [postcss-loader](https://www.npmjs.com/package/postcss-loader) + +```js +module.exports = { + module: { + loaders: [ + { + test: /\.css$/, + loader: "style-loader!css-loader!postcss-loader" + } + ] + }, + postcss: function (webpack) { + return [ + require("postcss-import")({ addDependencyTo: webpack }), + require("postcss-url")(), + require("postcss-cssnext")(), + require("postcss-browser-reporter")(), + require("postcss-reporter")(), + ] + } +} +``` + +**With those examples, you got it. +Feel free to adjust the configuration with the appropriate +[PostCSS runner](/setup/#usage).** diff --git a/docs/content/setup.md b/docs/content/setup.md index 3007377..9e8066f 100644 --- a/docs/content/setup.md +++ b/docs/content/setup.md @@ -1,149 +1,46 @@ --- -title: Install & setup cssnext -subtitle: How to use cssnext in your workflow +title: Install & setup postcss-cssnext +subtitle: How to use postcss-cssnext in your workflow backgroundModifier: darkTeam -incomplete: true --- - @[toc] - ## Installation -cssnext is available on -[github](https://github.com/cssnext/cssnext) -and [npm](https://www.npmjs.org/package/cssnext). - -```console -$ npm install cssnext -``` - -You can install it: - -- locally (`--save` or `--save-dev`), to use it through [npm scripts](https://www.npmjs.org/doc/misc/npm-scripts.html) (`npm run`) or via `.node_modules/.bin/cssnext` -- globally (`-g`), to use it through the [CLI](cli) _(not recommended)_ -- by using [other plugins & tools](#usage) like -[gulp-cssnext](https://github.com/cssnext/gulp-cssnext) -or -[cssnext-loader](https://github.com/cssnext/cssnext-loader) - -The main package offers -[a CLI](https://github.com/cssnext/cssnext#cli) and -[a Node.js/io.js API](https://github.com/cssnext/cssnext#nodejs-api"). - -### Install from git - -In order to install cssnext from the git repository (eg: if you want to try -the _master_ branch of the git repository), -you will need to build the package after the installation from git repository. -You can easily do this: +postcss-cssnext is available on [npm](https://www.npmjs.org/package/postcss-cssnext) ```console -$ npm i -D cssnext/cssnext && cd node_modules/cssnext && npm i && cd ../.. +$ npm install postcss postcss-cssnext ``` ## Usage -You can use cssnext using [CLI](#cli), -as [a JavaScript library](#nodejs-api), -as a [PostCSS](https://github.com/postcss/postcss) plugin -or through others tools below: +You can use directly PostCSS API but you will probably want to choose and use a +PostCSS runner that suits your workflow:

- webpack, - browserify, - gulp, - grunt, - brunch, - broccoli, - fly, - connect, - duo + CLI, + webpack, + gulp, + grunt, + browserify, + brunch, + broccoli, + fly, + connect/express, + duo or in Prepros

-### CLI - -cssnext offers a command-line interface. -Here's how to compile a file and print it to stdout: - -```console -$ cssnext index.css -``` - -To create an output file, you can just add a second argument - -```console -$ cssnext index.css output.css -``` - -Or use CLI std(in|out) redirection(s) - -```console -$ cat input.css | cssnext > output.css -``` - -#### CLI options - -If you don't care about a certain feature, such as custom media queries, you can omit support for them like so: - -```console -$ cssnext --no-custom-media index.css -``` - -To enable source maps for these files, add the `--sourcemap` flag. - -_To see all CLI options_ - -```console -$ cssnext --help -``` - -### Node.js API - -cssnext can be used with its own API or as a PostCSS plugin. - -#### As a JavaScript library - -`var string = cssnext(string, options)` - -cssnext accepts 2 arguments: a css string and an object of options. - -```js -var fs = require("fs") -var cssnext = require("cssnext") - -var input = fs.readFileSync("index.css", "utf8") - -var output = cssnext(input) -fs.writeFileSync("dist/index.css", output) -``` - -**`/!\` Note: if you are using non inlined sourcemaps, cssnext will return an object: `{css: string, map: sourcemap}`** - -See -[sourcemap](/usage/#sourcemap) & -[map](/usage/#map) -options for more informations. - -#### As a PostCSS plugin +--- -`var postcssPlugin = cssnext(options)` +## Wait? What were is previous cssnext interface? -cssnext can be used as a postcss plugin: +[`cssnext` is dead. Long live to `postcss-cssnext`.](/postcss/) -```js -var fs = require("fs") -var postcss = require("postcss") -var cssnext = require("cssnext") -var input = fs.readFileSync("index.css", "utf8") +## Wait? What is PostCSS? -var output = postcss() - .use(cssnext()) - .use(/* your other postcss plugin */) - .process(input) -fs.writeFileSync("dist/index.css", output) -``` +[Here is what you are looking for.](https://github.com/postcss/postcss#readme) diff --git a/docs/content/usage.md b/docs/content/usage.md index 222ef26..4688252 100644 --- a/docs/content/usage.md +++ b/docs/content/usage.md @@ -1,7 +1,6 @@ --- -title: Using cssnext -subtitle: How to configure cssnext options -incomplete: true +title: Using postcss-cssnext +subtitle: How to configure postcss-cssnext options --- @[toc] @@ -102,148 +101,3 @@ To know all available options, please check corresponding postcss plugin: [(=> autoprefixer-core)](https://www.npmjs.com/package/autoprefixer-core) _Note: order is important to get everything working correctly._ - -## `import` - -_(default: `true`)_ - -Allows you to inline local `@import` files -(thanks to [postcss-import](https://github.com/postcss/postcss-import#readme)): - -* you can refer to - * `node_modules` packages - * `web_modules` packages - * `bower_components` packages - * local packages or files -* for packages, this will automatically - * look for `"style"` entry in `package.json` - * or will try to call `index.css` -* you can omit `.css` extension of filename - -_Note: you can pass -[postcss-import options](https://github.com/postcss/postcss-import#readme) -directly if needed._ - -## `url` - -_(default: `true`)_ - -By default, `url()` are rebased according to `from` (and `to`) option(s). -This is convenient especially for `@import`ed files. - -_Note: you can pass -[postcss-url options](https://github.com/postcss/postcss-url#options) -directly in order to inline or have more control over urls._ - -## `plugins` - -_(default: `[]`)_ - -Allows you to pass your own array of transformations. You can just pass your own -[PostCSS](https://github.com/postcss/postcss) plugins. - -```js -{ - plugins: [ - require("postcss-stuff"), - require("postcss-more-stuff"), - // custom transformation code - function(cssAst, result) { - // see https://github.com/postcss/postcss - }, - ], -} -``` - -## `compress` - -_(default: `false`)_ - -Allows you to compress the output -(using [cssnano](https://github.com/ben-eb/cssnano)). -You can enable minification by passing `true` or by providing an object -containing [cssnano options](http://cssnano.co/options/). - -## `messages` - -_(default: `true`)_ - -Allows you to show/hide some warnings messages. -Passing a boolean will enable/disable messages on all interfaces -(console + browser). -You can also pass a object to enable or disable some interfaces only: - - -```js -{ - messages: { - // if you want only messages in CSS - browser: true - - // if you want only messages in console - console: true, - } -} -``` - -By default, messages are removed when they have been displayed. -If you want, you can pass option to the PostCSS plugins used - -```js -{ - messages: { - browser: { - // see https://github.com/postcss/postcss-messages - } - - console: { - // see https://github.com/postcss/postcss-reporter - }, - } -} -``` - -## `sourcemap` - -_(default: `false`)_ - -This option is a shortcut to enable inlined sourcemap in the output. -Just pass `true` to get the sourcemap at the end of the output. - -- _If you want an accurate sourcemap, please also use the `from` option._ -- _If you want more control on the sourcemap, please use the `map` option -instead._ - -## `map` - -_(default: _depends on `sourcemap`: `undefined` if `sourcemap` is `false`, -`inline` if `sourcemap` it true)__ - -If you want better control on sourcemap, you are at the right place. -This is the -[postcss `map` option](https://github.com/postcss/postcss#source-map), -so checkout the related documentation directly. - -_If you specify this option, `sourcemap` value will be ignored._ - -**`/!\` Using this option might change the return value of `cssnext()` (`object` -instead of css `string` if map is not inlined. The object will be like -`{css: "{css string}", map: {sourcemap object}})`** - -## `from` - -(default: `null`) - -Source of the file. Required for accurate sourcemap. - -```js -var cssnext = require("cssnext") -var fs = require("fs") - -var source = "./index.css" -var output = cssnext( - fs.readFileSync(source, "utf8"), - {from: source} -) -fs.writeFileSync("dist/index.css", output) -``` diff --git a/docs/src/assets/flux.jpg b/docs/src/assets/flux.jpg deleted file mode 100644 index 0510614d51094461f15c87e08defc49a006159b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90431 zcmbTd30PBS8a5pET?q*YK`aCaNf0CukfpW|LWGbYSwM-}Lc)?nVi5sbr!%7nNFuSU z8W1`XLP!EwmyoJmMiHnYQUbwhq8+uh1zI|twsvOPnd$$W(02O$*SGxtm-o8DOLB6~ zd7t-L@8>>0-TUbg%9qK=VW1ow98lRXP(M9JwPd|2DMz8$Y!n%VLb;<{9Q;sDFmr%` za=@Wn>~j=~=@9(uoa;dR`4~qO>bL~u{PQsa_=~*Y%*d~Q{_Aws;lF1*>-fvjZb!~K z{W5n>Mt=6wDk?c&{7TI$2gR>cg(k$tp^|AiY-i-`@UqV%?NeV%NXz{XmP_q3s)!gm0&|O7>P`6o>BgzBi zilU%UC8C2>Y#xJ;oHHjYGxQ)FWIz9}Z{OdwuLHFZlbs(L`s>I4-zI2LRdo#rA|DP< zC@niEf_VeXD-YFFA)kK@bF6S5GIvDQh^>Yjgn1w`uUMOJwjZ-LPe<=FSkAz<9W$LYY4N&3Xb5 zeG%8xRHbg&a_G>ZSV@^E77^&Lum9r#zaII&p8V!|vB>p)m0c*kth}VQvL+M}s_2!< zS8A(64_1|k%0grQ-%9*{{lnkf)^F}(Gq<_}{!q#O z|J4rvU;gYj_kc{-^cp4@&3{nXmt#@BA7W8Xt1~EPj2Fsj&zta#!>{|s@+d?hmbde{ z&)4)G=J37!{eO6Kd;|VO(opHBEEE&91I0%bp<+4$nD6Iz&6fJ0v^2;E?6O za^N}?ITSloIP7<*b$H$3n8OK&c84B^eh0n71&1pR*Bx#-m>uprJa$-i_{QM}M<+*b zN33IrBf)WtW3pq0W3D6Laj#>A;{nIRjt!0{9aWBM#}P-9<8{Z|j*E_u9KUdU=7e(c zatd$?bBb|FcFJ_x;UsV>cdB;!gOkGPl#|-&oYPgO51ba99yxvK^iOA3XN+^GbBuGE zbGCDVv&i{?^B+^KMVw{^9QB{+xTfJHuVzzTdsx{gk`G{eAa&_s`vb^zikF^hovC z;Zf@Gn#UU+8jq_UA9_6X_|X&X8RfanlkX|@JnE_PJm)#-`M~pAFE1~=SBe+MOX79J zOXYRm>!#OZuYY>`d6T^}z4v(6dY|+j^1kMM-}_r1A0L8Gx{tu8#^<9Tvv(B_`e%)8=J=RCA&shJ``orr_t-rMX!}VYKdiWB2Gkr^Z|KNMZ z_loaFzR%DYGzGl_Ekn1U4d`3wB|kSmf?t+jsb7QNfZq+jPcTlHa7-pfggJ)MU?wq7 zv98!CYz|h6J%Js?&SJmz_w%Rv7y7^If5!hk|3?8%0fc~@fXaY30xkyJ4ftV0$cBs! zWgFxh&TW|A@b|#r!1TbfKtxJ3wk@~A2%0AG)P3;!_OGdwxG zJiIe}JpAj3=OWk<3{@HSy7DljT1>TuL>)B~aq z@kQbRqMB$SxssAe`$&DHIkF=;kt`;kA%7U{7@ZU?iSCOwZ+6+7vU&ez_2!RaykjzA z>SBgt9>)g6vSRCF-;VuiOT-qzmbNV)Z23=IVq9gMCeB9jqcAD;l&h3);>q!%_%rdA z1fK*(!XFbZC;W{XO)aCoNxhedNn|G;PaIGDchc6R>ZEf?%UdJ17H{p{`cX1AIX}52 z`DThs3N7W2DetEIGc_r-CiPzwOZrp)VA_ zaQ1~qFNVEX@}m01C+XqorRm!A&of9F(u|ReuV`_!YT6j>@0qEYzt6lzccO2nE9kRX zepv-sJy{nhuk&1845ALK>m?azCA2Wm&oj*cA<^P}<)<>YhDa6aQwxUX|R;9+<# z^9;Q2`856;d|LsrptfMVaDCyPLVe-ichYyZ?|igt%dX$=x?O}Tk`!GQxCsgcTEVm3 zS-ZP-Ki!kKr)kgKy-|B#-FxdL+)I@&z4!9^mrGv0RP0i`v)EAluaX@l>XK)|9AU5U zYf+}?wCIb{^wQ4K<+5#M?PZ^rZ!2#vU#i$v(NVE1eo=f%{G}vQ(j)nsG+X*7>EHM5 z*f+HAr^=m`Z^_(c#j-2={r2zMKk>?@S6+R^Toql_RQ2dU>Vd8UUsvZ=YY#dc+ZXs5ryc)Ovvaegc~+hv@0R~ZQL30e5qIL$iGQ_-TBem0rAqnJ$?}u4ZzR3( zW~*!K{?@x~FShC0(d~!ZKj~n1m^wo{6`kL8z1(%{6!p}fPJ5oNJ^e_TOeHX7a-b{wu9ULM&qGB-*ey?id_T>o1EZ=E=g zI$wK!>b05DNGKg*Gyl(Eq?pa<)X{xE6gk7SJSSJy%YP+ z(7R#po_Wvzy*J+Xe81uSpZYB#hAMB zLBtKx?g$!Z`L~NkG3NZTplPM`aV4M@y3tUeizx3`hV|i|6_sY{Rs=oN~ z%cfQIYVTLXuZ(|9|Le@xyS{$OTa zpUMCH;D?<*eE#F1f4Tij^>5O@ul^_ZKM#JA{q)mM<0!PdbF$kJCkH&r5$)iFcKB%m z^&DgpE)cZgg=7fua&mNba6!4cxqEne!2vgXQ4UVLk9p~lq78{(cN|pb(=Q(T8-brx z+F3JRJl`-7SoI_-Yirr1f?7@2jmB>l7A7S<{hY4UKE->geoRTiSr;=fz#TWc+!3 z<2Qa;;leLVeDcZ9i~Q!-RoYOQC{Ozf?dgdQM5EDxp@HxUC59p|B86ywQGR}<+Fx|! z#rpO26P(1s+s6mvhY9oZ3(HU1oRt6n`}LC*JH8Tt%g{R__}d(D#a9_ z>VRLVwS;Kdu*@JLXo^s)7fjYcQ6#w}ziY6(s9ub{TD;w%O7xEOyW??tGLzowcAUJ_ zw2~gbF8SE5=F9vdn%cYh?BtiRq&QuDNw&@!E%P@m8YkganW09UXVoT+QVcb0 z87@sG5b>9K7H}prk7B4(6e@j8aMXmf4>v@=s~naM(^t%?CaZBuZ{x2Hv!p8PkW3K8 zmnf8KBbh{@aEyh_4nfjraG{l)WLA!eRXUp|zSt(?4Dlt+jCJbA>^#=|AWn`qS7~pf zzpf2%>`1v5v4Pmenm7Y%9A>fUtGi`C4~foJsOnJ_>Dz+e(MS{vm?CkcFT(>(X*4Yk zNm;7`9>q-YF}1+Y;7&}|H97g$_n(jrm=^mvyT(aD`G&5+(#->jSo!9Sn=2^KB^=IN zEc3n7c+4SQx@@>qv-v=mQh30xxjrhr@-Okq_UxWbofZN|fDhF*>u;I&L~;95o!i*4 z;f(6?A(@A*P?>1zQEDmLXjz;xH4V8%Tj7EsN-R<;md^ovyE+M0YMi)>T-QGMtFWWU@M2k3L4>~LYSgtR+jg0AbS2ToXMz3| z$`^yBHv3R<_sNFCXqu^O%U07pIkVln%^A<{;+{%OpR63%wyk>QUgy=TTOa%({Jl3_ z67PTX&GPV6*X0c&*MaP~SZ!!h}pI%r<*`eQZ1$-Hz1Z+)paM48<#8A?g-x5jBedRBCcFrL8Cqq zkx2>X2Uz^be6f6-MFz#y(9~)|G<{Os$1!fFUo+ja639t&N~4Gcnzzmx4En-JgQ<;8 zGtO^tah4q8ixu%x3aXs{Zem*kqPsRP&@SbgoRD`d!33(i>(Rk{j3dU>GPRgWKo2l# z*bFnzXcy~(fx0p`nseJiJtdCco7pbi_!c)((9xw&NQI4E7{K6+Q?AtqqHi9_Io_}* z1e1-A_1hQ~^uGLjf#2$%{=^a{!TIfaoTux9U6C2;7EdX&a8HhVHc!owl%TR;RE)vW z8G?u*l6EuuO=eJ(F`0IN_4B?;#+AwDw4YT-a!;uh4Y0yl7Rh38vCto@;0}4x7{h9k>*UAis~jyk$>M|Yv8$wR!9XB%bx=#Os86(#OKmCIs~hLj zjq|5tmNb4#-4}@WDK1M>_B#MSB~kJ)$W0GR7Mqn!Mo-IVPUDI)bs(BsJ;vzcbfInO zU1&pfO+g2G&k4s}0qRFfXI$~G2cbg`N8C^iuagLT(DcVq6`ixJi@PhT2v@#HRk}5Q zYn%=|d@SL1eyPyUp=v`}(NOV(+*&<#Pnq`fl1C2mf{`hIwb3-y?rv##QRp2h(J&TG ziauP|0C&)HP}Xl;k;_|_3S?S!9b#^f@2WVazTJ5vT~Zba zZxhj(S-~O#fs|UDBUdzoR|3~Zov6vvto8@9gy3HraR)lI#9%SvrD5O@KizvY--Czi z%(xSFdna}7`oT=bUjKnp->G$Y+WezADp{fN?9I+)-Y5!|6$zyAYSRKI4HuQZw(q8CMIBJ#`0X|mj!+v&Gxx_4wLqP%cq zn~=dmv$lo`wxl@5q!ldbUXXVM8R2|XuV_*hzHu37(ddI-= z7%h2V7eg{0C9$(BQ!*u&pOiP3j)qRD;%inKW;{}P9E`sQpIgGoS?~{*nvLa2x&?nw z!YDpV3IQPRtgIhS`m0$l;08r)q!RuCTYLLsy^i4^<&lP14@?944BrPn<=%sfVOPgC z8~o7+B0%f&)?8<8e`wO@>NH#+|}6Z0e;dD#Rg?hE991+ZgVC@?~Z=`aj9cA z>Vx@ZuOil6@UV8di@`bb5F1O~Cri{42DA4hfqy4o6Fih^4|(%=;ZcSXgx7vq zLqozN#*m~MLY$Y9!U6sDSJx)lGU03nVJ%#6h>uLc7cFp7GnfzsIB3#Cd zPRHzE?=}8DWA~w2O0p8UE`*|Ckh~d5F~q8dW<4%^OYE_Uo`Bd;?p_BGK3vsl%X!!} z$_e4Q+_09vd)c|2x0NGwuY7#@bxz9Q8>H4dcOL}1KJ{=p(ixz2$n^cPbXeu#&P#CF zyDx}2HUF;*Y1{2PJN1jhUcjuW6!H!k!z$cvVd6(wvo#z4(b+|4=pv*cu8#pp!n(4q zea9O@N9x}=eATJ-hX7q++wJYVw?omlNUarMv5+Y=X2I^uctc?K;3%o;btRqM`UQWS zP+dl`;?bTt7t2CFg_wXYO7N$2z?-_3VNH{PID@6OEM}cBHxBblEsr|$q-P^*_quLf0Af(BPsH{p>@N}1r?$={85L&+k5l!i32h3^0b$RndL1JD}Cs! zqf1-XbK=G@o}sV1hko-H-%nd=-YRQJs>AFhoS*UE(Qjz@#HYM36>YR2TU%!j*Pw&Q z=s|?q6=$n2XO(m-@G6g?=d5eEjT1;k4k8 zLyKQY&_UR5yMCGzhu|F6TG?1xWI+Okt6Aa8isF0t5JSOKv3=?Ru|`H!sYbf8qCjqj zq(!wbl|ZIKK+Rcz|1e`)J6Qzk-D!oqo>N{U%44^D11vgRIjq~|s}2i}VN?%F^e zRWhDes3D1thFq%4vzB1s4(!92WKB@-vnz=`xTcBq<5?-Wr4#=&#-0pCyLkjqsh)If=t+V6zmNgI-7Xs**2cz^;za`f;J>x zsmLBf_9H0RN&Sf0)s#_BVg=r#2Lzp2s4+Omt!`-v$+R-^G#{IdFFh{l<_PC@d_XsY`~kqF4-JZDd47hgWucm$tnNG7b`n4<-u10=%7g z2{Jc-b=3eXn10PD+g(|HwFWPga2w}$qVqH^*kyBGF9Qi&Ym!5RLffg!dEW6aI3iP} zXR0r0&o!^r0Pr2+ckT&<`yjqfFgoi;9#EIq&(P>$Ne>gG2uZe0ysY%-yaRb7)q>=< zTA>tQE7K0;Y09K|g}QEY-b?k>V^L&D3Zx{|6h5Dvn5X3R7r1U3s-FAoB_t)1z-_02 zTEKvZ7M+ zbx*J|f3ZyC3L-StxM5a1d!8GQKeOCCF~OZwCtw=7RaDlJj4ZG0et7%k-R8OZ-It}6 z8vll?4FehDyP{=*U{5_=cqtDob9dfosx(Y+vA-aV+~IYUQK(aOuo#;0g&f*~!z@b} zg_tK~BW3}CjIX8VX=WGIHN2ssS+|9o?6Opgstw){e|elf(-W0N=3z%v`dgL}W$sPO zyUl|)pKS@}ep4GwAib74#L%1dMX9j;7t4pDpsYwG3`KD-)<#Eh2Qj&AEAdARNjO7U z0#^qg3Cd8Yxn%6`uOa3I^}|w+Ihh%{ zA@BT6F%n_vQzz$+U>lZ}S$9D$J<2f&DA357$dIe9jr;ySR3sXl=3xw?EEa)W1NvuV z*^_YAEEaNak)+wrD9URdEM4J4UBQ<%ritjkDaQ&I{7s9L z`bt=EZ?}yG=R>kRE?Sx@b?G*zP{o0 z9ik6-LG&hCSzLD`XXe;^e1`x^p%po}!J*2SRJJzGxXLqH^r;D+<6J7Pj66zlCRV53 zRB32W+PoC>==^UwAXK7Bqb4kUqE1;v^hwTV3!-q;bS)KE!*-0KC4oDnXgda}qk)hk zR#Xb8c~F94h$rcjj9#c9k?<~(E?_v6#NM$QnrW?&vpbfsp5r_%nUI^^rM_6bk1n;A zat3gsEbv8Ota!xvD3fn>E9_nf`2q5Q-Gw7=98x|c=&ucsn&sl#dqc7d$R%_!zfd)P zp!E{sMq!&Mi6&63<%hp-{5`WQv@x2Uxsy#SM@yt~?3cQwRF+>u>v@x=c5g+v<(nqq z+1_lqVw&0T_{L7xPJN<0voG;>~(4q_)TBqI+-AmVl@d48!4+QUbvVy#J>W5|fJzQ>K@g7|0`$+3eoa;gsGvjwFJ#R~^^@hh zdV;~-z#F3Z2da{DT#&MDZI`%nSF5l8=y~h9Yl)XmygKNuj*GDI_0g23j3a&##(&N1 zSsaY)9)9z*Q~%jVqm-74%@4Vsq?=SpRw;o1VYaU^jU9O)(NoF9buV0cyGmPklvbA5 zbRkgUunV2dFQ;Z42vjlE?sB%+%i=+^_)J>5 zQMj*6dMd!b>Gj8#I#b9B7OT*qvA`3DJ1n?AOnPh2rqA{z=x{6XW9tHXl$89=OGBE` z^K!1{1OduacI2g|&p<7Q$m)WDE=;<-IYt4xhzlSi4AVsW-!#y3Ph7 zOOr3+gjzu3VELw=Tu3-x0?jvBal(Cx)l(!JzsuFtPve_BALE%t|59ce9r8@-V6_VK zdP|qbAxSWnakD*{ssXgWucjN|!g8=2q$~p!1ARjZY#D^KG=Suk+WwqHjJ*ipsU>l` z!OPOa$!Kr6^GRxi#Ce%3>3eT`)~3y8AP_C!-e|q-al68? zW_92udyswk`LAaK8Xn#N7qjaTrI!?;Szh$&)b|VdsFGaI^P~%JomWq+xbMZcbvXtfVzaiz zF^IRB3+lemkuGhJxBxH#B}9qlMz$NQibtVdG93tHwiD%+zEsG05Sz+_@Gz<+ha?`P z+v~*%iQJhrgR@D=9r*ma31RvD>&0NIWWTHeh{YCkzpHhFEMaUkZ3 zfnnrwclD1yIetndyD%Wpsd~(yk^+By0tPA#Kv)cQkkWR*PVn;zAdiX6?QgqzR9xJ8 ztTS@(Q{9|qDYNPGLB!hwh_+xTY&3UoE6e4l$C~3ZgMSDJD7?<}x-pkUbtf`}+ zDSuhHMbhmTNf92VcA8V zf}B7;xyj9;fxbfPpz;k4jC)Fxo_Hd?QH><%7FF~>bI z*AeKanb#7u)%qYoo7b`RWI!H0rh7ITNGTl7f0G{TJ{jUn$sGyQ?(UH%`JTJmCU=e; zJ=Wf!6|@^}aZ41DDsU9w+Ym&q(OmRy8GSB&XIzg|V;Fw!{2w#CC(3#FE`nGR+EVTQ zDD%jsp0}$X+^k-_*%e$E$E+yDE$7_hkqW@QPn+#ifV&hr?XK9J8>;Y5sr>AOS9;U22(xE)`{F_-UW9J( zn}3=R=#f>F!*@%iU!i|MgV>UZr3ZLvwJJoQ)3qs`H&dYc75?JXc*eWTj{K+Zv~RGl zUXR|rAd!#gB1w|HE}oVGx}wf<}Fi!&@}I6(y%t;u@+7Ph64>-(r2*P%a% z5eTJWoJ`oHI2k1oCq#QHnhU}Hg4qle;Fc^hM40YH&qn^TrNetHoZEFK;&D92FQdgN zebA$XC}5LzJz0sO5dcm#F6l#WGsVlJVKnzGVI4n&yqDWk?%Q;t{cHsU!;uX>OP}H% zU25bveRZV#tKf~fRx&ekVY0cY@Ls-7HEVXEPcl0aBZ8#9MoTn1z%XlQdHl|iy15v? zo|{}YtI^wxX_m_eM!j5?8w6%j1N{@WOqosOMl^0acfn<`W0JZ;-kDjHpWAEu;{EO`>`Q72?epfHSwu>ZgKaeNI#vh zLotax@08K{4B3tIH@mefjqWy)Ono-`nx-QWlTgILD-$@{=scAym7*nzsvj&+s6nC2 zoG}(eEG}240~1SxRDmE#v14Tjj0A`GENDAYrBPBoi`&vp=!i?dB@tQ_t0~_W+1_*s z{m7+1C%%c!8%65wiMy(vcJHy6ki>rHTh1;UJ+4iN;&-cD-Zeza3>8w|PPX_{G;uhu z-j*t1EASj6KKjn0mtVt_K%GU=_H!ua1ov)GZ%dg-(miO|!>bpWlDlv&16ieHa_7EG zj^~`b&rhGQ^q*~xRyIHps!XuP0@HDH4Ip6F1-aFi3usVeLSWDCpDRhGg6>LjUcG2n={v9|~pW z<;p_Vg3gPnyINf2)%^4+p)J}RASj`D)|dO;+?6AV@8T~j%&DDDSx$L6`P5n; z2tj#-Nk}@08D=O{3xHQZV!|pElp|^He0eQ>mB9_@xpC?31pa6h`AwbL%1NR;EIq|*g#-(rxMCid+jnFRO3gsS_ zk#6w(Q{z=m4dY1sR^?x~CN?0QjwqyjvDQZAg|o6LT2k!p6bhAWy8oW@Dh?zu%4co>U`)N z5*X=^7Zvo|E~^dL7>s`!J2z@ZxHJ=TO`W(mx#z*Ym|Y*A`{JHqbkA7bP~X%&2Zvrb8HEO%yOipXp~Dz{oFPbGQ3OzB^3mYaDPeHrda49*>} zJ^Ed9qRG-NM~`zCjN<55EKJ7;N^wcG!;Rnd^MpupVwX>08H@bE(yN9QBb#Dn#2;PuA?hCTGcAlK5c95hwh%>rl{k{G$=)Rv<#%6fTVp)x{{K;A*Mm!(ji>= zQH<_)(hr=De2~2ETx%dTsJ^S=)4R0!f_KXam03 zniSBOfr~1H|Av1a01Qks4K+E&Rrl^VV&@3@6lTM^d#W_Tx!u^@Q?tz0`pD=?2D2m2 zJs!Xx8(U(%Fn-wG8|QxWD4i)XDI9DY{TT|x2~g?hLZ`U{F`q=$)P3cYQTePdCIPD) zd$I1;*Ydba^ch9;mmJ)?>!Y!I9FlfF%HIr?Zml6n&lp zsMX~(P|I$($&x%XAQx-ZDWuCX0rh%p@MQ{>jr4ES?_Y1g3q=vM<(Y{&u4X=IF>3$Q zU7tJ2$MMY>WXgy51050mEK-3sJ8YWJ1#}0@T}#T`I3N~NNHo(exGE{`Yi-9c4gdx+ zC9W6@-ju}89;%e|me8>I)epLghNG|EY#zN?{wUcUcF{9NTo8cIR;dPjOQC_g0KPrX zY0j~D&QIeNnR8OE*iVm5P-mGS^Uvbuc;1pz-z)t_PTIRw{H!aMK>Qv1`QN`>!U(-f zV4t7i;2rp3)YlUV1p#FntgKOtT^A9Z9Cuy$`32;+|@p;27ik3jpUClbz*iMke-Gfr=pQs?L&t z0a>8Ui~b1%;ak{22chrNcNBY8A+a|#y>9GNWeVuK{9lR4wH6)v7PH2c!e zbiez4DXo?ydM$seveEan(A|<5ar8=Ih0t~7POxp~RY!kSlo;TLG`KE351)kKMo7DB zt=CE}C#Y-gPAF*Ks;+%I*81f~K}+V?;e_&7;c%&(p86;iqp{a!^;bQZ(f zw`*q_rays=hj2u2xXKDVM;Bx^z8yB@%&`$WKYCskyrJ^p37MlUt8}IyTY--fQkNF9{?l9~L=J-p9SyWHC+gF@;4gfFZGi| z+JWC=XFgSg*)|<9-yGoXKoD0ppVU9S#>q_GE87CVL$LuqpAp-*z-1!mRUnM!w zQzsjNmtp33W)(VLxA!=@JcnNS;^D&4P!3^T{f!v<8< zyZdsc0k?^g*t1KFzi~2$an-K^{E9g-!E1ol5eQVAVa6gw1DT;6ce{FW6rLYKcV?Y~e`U|mc$$9*DEyu_OCKr@@oHDRrERVcphL$86z zklDkI=6C$N<5yGO^ZRq28KAkO#b6;Gq7sZ?xHgiP21}<~B5668T^E)P9-8v<-t|5H zX(0J6#y^+k;q*xwUx7I_D>>+yWG!jeEDZM7#&-jdY+T8yKkUvV<`r_(wU7S#)x^Uw2aHW8#cO96Z&Ury6<>g{&$O;$u&DZ=$32tR@MX?gsz*t|IRJ7!8&rQF)FLM4=N!Zg+rmpty&)bd3Q_4 z)@xU`z5Y?wE4SahV~zXb%KT`OmCU8%kVFhFde1!M86~ylbfkGP%{g<-#U%&_=6P-dQw#M|%Te=%ol_b?rZV|)|4%&H()#4Nxne90CAFhbuOv35!*dZrQ>}5 z_RQ@$u6MV3b7};$n5pc?9k9cJ_KrviFME1Tg57<{!A5nS520EF{b9{Q zS7x;__RPd&awEZ{8hoepukp;=sbAB(7{eZX2<3H_K1z^E#jvL2Sa#7Sy0oOHA8o5t z#t!yeVtnL(PR+VO{AQkEhAyKWFf%QtQZBe=WGmXjs-6(*0Squ!MxO_K90%~mMRo1Ob)tZjCZ2+B zGDr?!@J5LEB4M*JN8V)1WQlJ_&4_;|Z4aw?ER1oIZHMmnSf=(|e&3m?n?)0=T}aOn zNy^PgdvL(WqE5*pDtvR>cDm`v@gFa~a3aojx0Tp?vssWMhZ6$N4tQx29aR&^CA_&V zQm}{czUJ`WD0&+-?^fX)^vQ^BcuWCx>he?x$B}%=0<~R6wlb zwFtz5&=n*-dBDuF*u?~$0$UbK2DC<{KLx?4p+{q92qGPLXk7u^1^foc4H0i|C1@iP zO+BD{@{t26gEBoLy7V+C8tudGJ4ZOJ^$;|H;jsDRgl5xXbdY$0xr81|0sfdMqkeEp zzJ6lyX;c}DL};W#9!a01uMy5}vxIf%`9%4+@00Mu*J&4<_8%>c4yaViXV6{9ji`;Q zK=|l1J}QXbMHB?hw_VyilM{?wa|nDiNu_DNuGna*j+~vd*0NYZ^X*raP~Tf-*g5pW zrSgvcV6fyB_4E7($%BCe-^Y~fP0pn`S*)@` zhzALrAzJ(eXo1SmeZZJ&f*3G>P@8~(2`(BSz9hu4^#Pm(G(pfoAljG~(Ez>Lxm?>2 zc|t=(r%XgT0+L3~y2iU!va1nny3X#C5DJtMs4XI)Pt^;^Csw~ZpCq4CQNg8x90Mix8o9;S8OQG9pL33Y}v8WnF^ za3%yOloyQSD>*INitJ?W&6Yl8f+xNLAxuFT1+8KFWcgPP=&RCCv&?aQ7Y04q&kHti zC_qi3-rx3eK^fNpJbv>mUmO{k!bnn?%NwD(0)Bu{Hb)}#4SaUqd_p{KdJyvQm}h~FQpkiAUev-C%A$H$ikGWvLFLAzPuVuY*&+3SEEs}P(xvF zB#W_vn_DhL(F%KUzI!s`?rja-k4r}LkJ7VMWqq1keLx26R{EHL6$C;{6n9$OkGZVd zeOWz`1C(5*y3e;1D{}=k>%1d!Ha;i~Sw|qTL#QtIZK+}B-S7FQioa^{b8K$50HxQA zy|PJtvs^*->?Epm@;!vQ(bN)C^9;C-OdyCtU)bI?Lf8{Vgz;DzgHa-cBNH$gkmeLn zj}a+BMhw9LLFy11mrd%8q@TeEfyv;HVW#GS#Ue;Rm_#Exia-BNi0e7(isJ~#_R$#v(+}j2{ zwUZP&c;gUu7nhxY!(gz>;=OSHQ-jQM&9O*SX_i~5J~9gG~etXl=?c{sUsFx&E}5<5746rbcsf9#OSU}70I93HYn zz@^Q=W$(lAOiA)7%?jFS#}ksgG8Jr(t64n+c=?o#6^=9(S<+ivAyw~q z+~)!3aZWghS=ifJ3MOKMrX_dks_$Ke?{p|Vv0ii5!dcC~9LWffpV!daqy*3{&22`O zq>+2Go#qdcLhiq?ui38ouo+0(I0D!t|5E_009v; zA3~kZhvXtzkd$Q2I^81SgV{qv4^cjvz1y5-7dfPwQT(YXTSahjgZkMg2e6u zVo6+vS49kH2eW)oq!83t^2U3)ljja$=ks;ZVnTuQpuyh*DD}fE$aC~oHsTUNV}2cL zoereAgUA8N!+;%uczlFI3D^k`vBYcN<@@`Ql&-ey3lZ9BWyk=KDai!jfJhV#G1O+h zlUj&yzzd-_gs7_0If(e9qz*1~>5z}wXDr7Vn0EpkUvbbl@4Kg1)7${vss$kPr+Jnm zU2sHc5mv_9jX^JF6-a5pP^)6^UA)A7UhlowPrt2=JSBpU04A}~frVq-&Jx2T7M*vX z+e~vm8VPo{m%<~pMpubeuQ+IylZ5F=NitNFJz^LDNFr+Rcu@?h9*k$FIM{Wf7N{?KnSN0!#qHF=OeBcIxkhhG>;f(=fqcItKRA)jSX4Lw;sQrbT#9^&Cl*1%FU;_4ve z0;k%z0!9k|0RTj~09s{#B*CtZMrpfu=T9i{ol|!fq!LqYH)|eo4IO?Rd2k8r#C14Y zIV^4yt2AK}T^yTXqm>g(_dbA5V%|iawM#86Oq}C{YdkVt>Dk)u9K`%bhrCD$m|nM| z^BUaySk=VSbOm$yun-asuw0eo-U3u6iHHkAh7sxUtRVzuB!P#4_-kYc2oB~r83w>5 zG4kXHqE+B7qBsSZ5QvA2q`5U&EZ|Oc0f&YknWK@6%OO?*Pe2Yfg3wZF^J;KO$kpnr zGDapoh)H1JJu(2Y<#&&o!rj$6dGpdeC>XfqU5MX8pkV5C*sv+RT}1wA$jylL#9KQC zyB8JrZkKyTcaWB726ObRNksjCm}SojSzNA>ALyoDO-#V}m?(-w%MzqhLj;o4 za|w0l=&t#m>i&QxH+=uvu1OjlMGfDT_{NF5B6^K}ope8pNwW&Ks!b#dvw`LY`ePrE ztpmjkX)PnBzqV*4@|Cd;d4T6PAr8TH;5duKnkI8cGM2SroQxquRHI>g@>Fh!?LoFN zZcesAKxpFfMXQLy&RtI?jZ7&z8#&W{0Q)X<@z*M2i8R}49AJ`hBAAPpQsxu7Ww;tr^o_pR$l=V-$+Pd$-0a!xvN z(hI+HS0xc|<%XW{v4=MPYTSaK#0&z1GUgXsGb0aic*&G&a{5I|Nbmz|LqIRYodME^ zcy%TA2_c%rW#|Fj5uyRBm!%KvWp54d3{*vbBG_e(bB83MyB+F4Ge(? zjn)@l;ATNPO9u6U_sd{IgcaV|1FD zO)Zr>Kns1cK?47|{{B;aI5 zECw2q5g+6il9&gyRQ^o1=2%!v@a6px^c7x{7F}Hsf^oG*>~eDfQiKTgEN1p&NBP7p z-^($Q0wDh&cV0Ku4Hg99$Vy(bv|ns(%{8sTba13KoH8Z`NLy_41Q1VZO%%h=ATxl9 z1OrVGL>zsHYwH6Wt(mV`q2)LRfV%ht^nlnhGU5!(xr;t&$YuFQ9v#afh@yj>x!z4U zeh(RtQ|UOdnb{Go(MRMpW`5t86+7o8j$mM4BTsL1PTJh=!(BEO51iLF*Ccyxa*R6> z5J9Wl?J>g2+DAD%Nv|!?;GcYy5}Cm6`hB>>E%Nr^g$PYdIr&a(dCVzszw*Z6ZIdCr zMiHL+IZF%=?NHQ4u|94+T|hYPp}5hy(2fFiSAiSCw$e`kA7DO7G0if&Kjgnkr>kDg z-Kf6UYDhVASy%aZEUHpMyyarBX9mWJ8!TzzJ)7M(t$C=Qoq8~`%tA9_5m1Vm=FF53 zL_?L0h_WG>IuZ=QS;)qckpqzdIcJa6AMjT(dt=p1-o(d}{5~GZGSXYdj5`g_g2!aF zeuB#gRVnxQer~^@hr@Mt4eNmKRf@B~uZ&t7Rtr9@*g}fOWw-QgsrMm$T{F>;mCD=Z z=3JrsDo`31<+NU?WSjVo4wT0;rR0wMNNLs5Cihky77r1 z(mRKIo~W#95$y7k0*KCF?SYJ{2Y+k&%!Og?q;H;3fsyM0djgi+D20G%&e|}qxi-lE z?3xAD4e}hxq6r?{1jTBJK_UVO6hR{FDLZ)o)Fa|QIdQ%woCwWdSEJP&S=4w94rQ?h z8R1*;qXeI=f)lj;9E*V)fp(2|HO|i;$X|3ldmUXg0sU1(CmW8eE}P^nZC+~M(*DTI zAx|dc8*NxVz=h4%yGVol)xJJV1D{F4;y|E1BD-pCLBptKbCHm*OL8+>U*E#ij}65oiq5Plc66u5_tK2 z{s3nmbB0(41l$(-NU8QwS``liU17U_hj-clXV%FvuCqWJF;9dfKz!=SP9x19G?DdjI}w zjm}|buOB95Gu1KewC`9Y3H{-r6G{?vZ2&}6GMjt4!V5cBD8ZZhknPYClHFXWsvbcH zwXCHR8-wM#itl?4LZb%h-vfH4gh$Pm3ZlR@SaeD|7LvDUvOsMw(VHoaG@U|_WqI%P z>pxhi7m9D3vdMa<%%Ve5GfPTvzaZP7LhECqXMP^vuvNWCZTKAyy90jg%9hIzjBuCIS}l z0F(>j-$)9n@L%5e#$G2#yWWO5`~*sJ$Z{)fxS?>M*V1JU!&Ijvf42 zqM9}LK++O+xPLb;sV&ku%ZJ=7^OI?#X=mZ7yCfjtRroyMbps~KUscu@*Ut(i2QgWp zCo&+h9V3Y>2PXK_wKANRlbDjgG$#V~Lg#`m;DG5qUCYu+MF7M?$yvgwcdxH*jM(&W z!ENIYTZ`*PQgr6`4;U>Y2kD*JLLw$Ff~;*_mAl=Dz!RiYU{j15=eh5ttEM)W9vu*s zl8M^=hrtMezCqA(bSZ_B=0S$Na41ZY7hj zk#l}0w~_6#ZY<%n$Jrd=apyS(A4i>Jmb*mle>4lZBrr=xFs_>|U0hQSi6-?dz^d^3 z#68wTq}D(RR1&xAuFX!c7f>w-9UP($0H_>_p`2PK3VkEk>26=!`Nd1Gp*Q}Ed1$&U zfypf&<)m^4LydHgTEgvy z6tLB)zHLolYlcZ*%?ed``spC+?mFAVZP$S-g9Kbig#_B}#Mj<`38qTBmCAsBjTnN9 z2?3exMIyK|B}4`WP{2V6;d$(VN5wmi>HdMqYMW~O@R@CMrxGp1 zChv`B=Z$3Fi%ous&C{K%4PoXaZ_dqopQgYi(Ww!;vam%gb}ZKrRxkA{R0vv`xb;}? z3;>8B*03OnWiG@cTzww^kB;EHWS*0B(UrG}f1PcjCi2oVJ<_-eox-Cx7 zMja$b9Eeg3VwYvW6tF9sWdL;zsK9xa!T$0!p>@tg!Lxd}y0!1&-MHqvr1mI)SR|kh z_LRhY-egAV>R&~MpcL>e$WNaw2={7X%(lEJtk|V7>r%nDN;yMBH0QFAtAdMvz_^VXLR59{eLrE z_sp5+JkM|6o@FdFYs{r~_>86h?e6HZ-ZE}tzd>t(jncMJgBrU}S&i-x9-o0dtb(v5 zLSYvyPPyWdbIbON@-Da|;R5^YtkhKH&6G~2Sn6vgM~SGeN(9+%O)TL}Gr~88!drU% zGCbFhEqT(KmLmbNseDSO{d-0^$~CO|-k9&1=S=@;C2iSND%fpvLL9@xuBn;$jxz8$q*M0vZFtetkbfO9J0 z&N{c1sVd^8umB<}Y)we(2J!Z{JI;kbvY99`+G$#n6Y{+{;npVA5M`LQtJ#+WWQl;( z^Z)@u4Z&8W^WD4qJmU`2MsQLQ`Tl?~dOyl))um8u)T zJ^(>^$hD!6Xws4CnV6Ab0qM4aZrYd5n@=sDcomoJ(Cvtm$grU97hV zKxxjK7w1eI`FWrGN3xybK(eo%cAtt3?mY(&2@59NxqI9I@jvet++9ePiM2#1l^nPW zWdaD*@caj_<$fM>mR$DF{}jhcI&iP zS}0_+>TKFncvQn;g}hYKEtfS90@sJ^_?(y}XQv>dlX-n-1eEe~E>{<71lYQt+Fk1= za)xZHVJN;MLnc{AbeDU2ss-#1D}xg*3?6hSDV@;88T?ej(?<%dSwzy9Uy6($xO)#^*R^)-{~k|3UD8bV zi4ql{Sr(p3mA%GYClpL^yQab&0{3g@@XGy?xukktzWjlApN=Wtw9jM9PbJ?^XRFFA zyL+l2I#A}0w|ZKoaO-B3QWw5u1s?nOw6)ydMsFMVaNmDwgAYrrObxAf%GG_9?&K;w=3lE_L>tl@Xdjh%K?3uXUpe5J+Q&jY^GoRbf zZhi%i_1NJoPep0K%WEfNH;GiGeEmUFtEO5VEMTO0|tOc+r^DHE{~=xyMOmoXswNu zW6-~yVFG_et@P?z_o?6>DFzmOnQv9PViNjj9Xlo?wySWNNOD%%o0`>9JB48fql`RX zp@5j`!}d2(++e3u-^sB-wp;d&!05p3;fGnCsqP8Y2jwJGjWVsfVbcawzLZpPn7Es# z-Iww_v&cZ6eRri+9m|pu6?MPo^E%h0`XlIyfu+3KWr&HoJugGCsaushq1wG&4XTmt zBOQWUlfxc=f1!xm1#YeG-0_;-0xQGJKc%eZPVE3ow!K@^2%8vPQ_jRmo8mPrZoI~w zlE$Yoa?hTy}p4;mLQ|$dog@ z&ZAk;rtTH%Qj3DjHmpoAGVtJA-gtBuyUFqfJ;=6`dHnb3;hC5iZ0UAB zi_gpHCfYe!3NX(+QJDQ?gHsEST8i34&O^Wq&6nOg#igFYJVjA-j^&#ub(oXJbrH^w zfg+}k$z8b?5c6&sIAo?w3@>hS$-yNQtm$+4la_RHuV1_&?QMs=M7DmLKCGZqRlrxhmKdK~ zZ_uq^loKQ0651*o8Zy)flQleLuR-ooJx<8)dn(nIk>TtDhi7nY5X{26xL=KD2A;zgV!!2<_5MT>E>NMs zS3SVgKkx&>eo((Zlqp$C%yU$@y>-jrx%kqkxm~9<4&EF)|41sa<$R zBaZ#^{pHS3{Ujp+A@c(zBhFz#86qx5)xplQaS3ni&t%-zOlkcrrPJFP3XrZ>hkk?h zeyuAp5i=Ln+i~Huc%7YYfnJ!@x)QOXEdoL2#@p6zZa=4rpV|TzsH6#IA>SLz>n7XC z-TUx3M?hZ`_QkXW?iYCSBx^Ku`5Br0YG+MgT>{nQE-Y@a#&<_}dOuIFy<`cgzaw+GiD5SafHZ1bc(KPg5oE<+LD2-DMFLo1w819;k9d z130bak66iZ2?qy9z!C~>@&sxMbX3B#@jvhQl670++=td3Jt)rSVQ^3GK}XnzhmCL7 zReQIudGJx&N#oqRkgN+~pQ24W(lk`IeTtS!PL1Ap&s5hq8w?fhmbnB-y`;4Hv*Sdm zoL0j5ZM&s;bqwmVVKe*cq{#AqAJH^xSng@=9RDC8G|<{Qp<1@442|Gw85O(`PH1q55^zq{ zl7)gA;MNqQdjF1egmdIR zYu!7>>vWAZkKNOXjV||S_s|^pu5Y%!43=v_@}*zaY1-8;>=2@KuGD$0dxOBQZH1a~ zsrOxMM5c|~rO5ihyzPp|(@Z+#Lg28Y%V1Jcy;D3|?6qMxkEoHXsQgazlsYkfm2&NS z<4T6Y2rH;4poxQt*86nBLTEG>oUfe3IFrH&6pt^YE9xZ|84*Ztu} z`p?_$wDyAsZ(A%<6S|$gl{(l^)GZGus{A+T+oxseyI1gPYu<`II_A1!yC;w+aP@YNZQfb@2F@}&T$j(B z6WBzT7l9qIFtG(alU=zmM$) zMa#YrXPz#92S;2@6_!NeM{0rYNpML;wSEA>GF*ZfDS)a$!i!f~|Kw|%m&o{k{;G`L zHFDbKDyjWc*B}n|2)bKuFfD|Qm|ION4A$(IlHtuz-6IA2sq{m&Mdd<1My#?U>g3$L zjZetJnLGIWL|JEB2}JHeWR(T7rN9KbQnO zx1sq?QB4brRko{Rn@lvba>P=l@%Srt%v@UZZr9OH@u-f+r?bSn&zj&%6PC`=$>5$S z0Q>GEQiV$_tV!a^6T)0sY7<=|5dJqq=DyOl3Bdn8Rov4cg}P*PaQZ;J0dKPsZrp_1 zaj12J#|-Os27?aYfJ1i2mrDHq-!O5gn@G)2J(mWxR<6jJ^O;%7?KeEGuPu=pB_XJ` zFH^hyZP=Yg4fnX#?fU5l&t)_0;vd5?7(jLIT0@|f$eTJ7*rs;3(RzolqDDP#1>ueF z$&A1Uho!!o0k8}iz%|vwPW5!7WuvkDMp3w-n=UG!B~foyVjWnw!(>B`%1MWZj{+|m zSgx3$!s%<4phWoOJDeT>hf=hxgp!lafiv?ldmRO9!N+1+Thsljs&8m)(I#eA^g4wejC-uKx@XBv^ll-tJd&xzj=^0t6Ap zp?WE9h>R&qKi#xfX1kIEetwFm+$T6hMCwes{4uJRSILGau)YYw7MM%LJ3GK7r~rN< zLApT5%{?u~N-bI+;MhKH*ai)j-b-}n1~{<~QyVt~@QG?h=g1gY>xMj8ee-XGGG zSWc*98&IiE=SmfHw|i>h^G~5q<)B8GqQ4{)aB2zg2QRMSR05iJFCC-6<=qkoxqsd9 zql+LNSfV|-B!GLlsZB{W)zM5z=1%TPb$8fUG2omkl7Lec&d)fP0ds^Uw?iK6Sa&ve zl|k~74F1oIc$-;ST80HgpHOhY*HM^n$U0!TA?kkiy5lJ|&cVE}-bPdcHzlyN0_YSP z)*5GaOv?OIR?27x(AsEEv}I0c>dK>^Z^8~w{c7)1i7)PWJV<=H}>!tr3)#&UDGDG!RgRi7(E!nf~p|OH?`viAh0>lRl zFg_h&hCjyr2<|A2|A%M}aNy+1W$-HxyvsQRe=2*%hCW>@sHptG zLb15#GAl8DiyMjV>cXZ)z8{x3?wTEM%dG7h&m<#rotDQ}MpesJwj(!USvU5D&-+845~v%As#dU__meV}he zr0*cJ<@XV1YqWOnKB=X~ckhExup=Or%NJQS6_oeqRrRs0Ogc8I z_pU&J{P|;^RA}GYEK*wV@m8AZzC}KsJx|msID}U@6-zG;0lDScRuGY`;&CkHSn7t= zsfLH6CPYoMf9cqW%-D!jnC|G7R-7S@rM%U)z;xdf*X=gm?S;t1XAlXsYL{{N0Ji+O z*gbc5#+z!b%9YLZmiIO^rD}S%%eEPrWG_#5(LUeUq5H<@4K>uMh6HX{xwD+Hl*T zJM!l5NO{%W23dUMeeIt0jO;`IZ1~$@RyF9jr-!FglAvNiM<<`J_c*_2VRzM7*hWqD zTQ;{Gt!8WM?Y0lLmki9D)e)E6eaTIG$UWxCW8WQN&$Gl52xWrnY^)=;I+lz)(Xx^F zU6OFwAgke<|4)7kjIQ<2Dv-V(OUY-22L@eL>e_9zza~v};d>{a&p1CL`LUizX~|)U ztG_In4iAXwaYx@hmFTeA6Wfusu~j2kP&c!nWmqD@_!Qc%y>zsyni`rr#QrerMjxx7 zL8pU7b`L!JTRYyUUS5`cb8#7#u~&!Zs6@E_rDINZL-$Wzi+q{eTQw%JQFFBSu5yC1 z?2Mp3aVqU^{Z?WrgaDl@f>Gw=AEA zG+U(~juBpU)KQzha<|!TA)Vy{$9Jl(%b!2WAw~ym&?_t zBgQi2GUPL_cItnad$?LA-&|xhE8CQsZ(zLkl!2AKQ??cKZpf~mODhSU*c!{T{nDN% ziX}!`ro7Cf?#D7&VJaZg9D*sI@76WmbHu5eG&0$O^~NenliHnJx?aB_ zw@Irn^afnXwA$D+xip8SjyR>EPWJu+{GJB}hOvW9hdiFH2 zJZi#Wp7+!#d(tk@VbJ1X&#~ESl>u2Cf;IHh*b#R{YapFcNi53Vm|&8fe{3MRo)z}n z2fHeE5Ojd2PtSDhe_p?^MfurF#Ibb$A$9}1mS%2ul~S?E^^3;%f(1`qhZP+hmZqzr+1PAm~msJ8P6x4Z3`K?iyNk4{iTR zL(q5Z_7T!~8qZv=Sxe+D0G`(2Fs~yid1Qn`u&|0#qtIAFj5voE*j3sZK0U|9eebh9 z{LxwIFKjE5LAJh~a;5`)od$eV@vstPgtva^I&?f^Xcp1D>I4A0Qr13r)qXb0G5ipU^et44+WRKPAHE`du-mkZWBQn?eNHC z-CfZV<3Qg4-I!9o71FF&pUywu@~W}YqJG`)HA#b*_B7h3uW||SQzXtWV}B)Ha%kcg zzB8{s{^5`gHv4cHB9Ij`D z@X&9uzN7c26bhIDMK8?y>5d2QDadaS_w>Y{k+fBnWsZ#_?OOBzEQdJe#OfyZ5T_P7 z1ZCvG7WC2H*@ZV1X0Mk=>E_i=u5Dn3eczmzoqOv$jh_+IwB^X`;^{djqm3Z1KlS<) zIfR^G#sgFZ9nv&JnuO-X(YWC4Df+|N9zU|*#gJa*4F>;+XsR({BKIeEv5#G)2KPEF zm)x3fV?KKgH|6_Me{~@@iZK@doFOu{ubCCXe;WrOK575?681#>l-(ez6kjI`8F ziTU?~C=p*F?NoZ4Uk#Rg*IjRJmp1Nu8k7?^F>B}`#121pA95RXWqzgfz7o5{o2|mE zEw!`U6t{iO;jo6lz57v@m{j($Jf&%7eek!#0mN%JHcdwUoJ^`|dx<0=V>PS>4xv5d zaF!&`n?qZ7Rb0(~4&;1wk9dD;?NmIHz$L;=5qsjxl&zg#!&Awl>`xu_ljliJGz*L> zc+#wPN@1yAzhE#``+PgT6sWkBgC+r?k%x!;7r}%v!CpAuO;1K&bsrHlU=GXk*QsEDCdZOo<=Dh?{we<2Ml zF%4GDcUJY3uHLuIxj3+&$*M~Ax+$H0zq!P4YEV}46S==jy3`_;k4k#=s@L9R7d;m5 z^R6oM7<25qea9u{tzgn~iAAMvhet+xim^07hZ|@%|J-VjE|*TfS}bkHbI`8pLl0Fa z><6bZ$#c?}eVx~y40C07O~JfvstQxN&+heaxnVVd3pZO=f}Q3KM&T;EzrOc`gJ(sF z_k_c9kOXtS{Q2XU6Y2wc(Ov?us`#AttD)5she^w73!Pry$t}D3CjARN(A!^sob2J> z%@lf$v^%|@pibr9e$Jku#nqhjr3QPdT>+kC^Bg(?>S0D6-dI1mc5pJOmVGn@V`jCh zldFER-us`bU*|sdCAY3^Drt?%f`q(@{P>Z6MKmiQ<|{e4*M=9}7k^|dA=oE9vRkc! z1|1%`H{)rn9{ht=&$x^3%R{{PclwQ~p;y=2u%ATssTS>@OG^>7&pWL%% zfjH*fj`TT>XZVsUk7I5hKF|YLHBR)Rj+`5>Mm&HTA0~DL_Z|{uRl7{)(r?#aXrAj} ze$OR?!P|G0UEKjG!?n(3~(YpD<+@3S*$ip{+d1$kjFvl5xuW1(b7BeN29+#As zKr?^saPY{*pH)|ddQV252FczkFh~nn<`g9}#soHY(Q4 zYI`#c0|zsI3GO-Ce4Z9gY^3w~V-jE&Yx2pCtl*+}fTE4n5Gk)&+q5U;eSP^9QK<5& z!c@>EW+weL$a6Euh$-f?zw^rBU>Dl0wRx)BWU4Myoj-~6Y5E2oY*4X*Zb?GJhbmu9 z`(JXK%75;!)kPA$a=3-naL<2NzuGK1%~ z8WqzjvBk5Ko7~;LIyg4__|0#tG_0;%{ibp?@%*ayo;rdON9b;*mvyvGKQ@2vV5MfMajELvOOL=9t?s|!6RzcA^+9w)gD z+mjx)3iTKin%}pvCcm;}hENaJcpzYcl(?#AK?JHgva4G=fP?#4pG3h5&ZmpI<|*o3 z0y+PoGR^!>S8nc|!yK81Yqz$?o@KrpS2w6olBeveOgwdJ)zyuGo0x$e9XJudu8}Ly zL}aW5qXN7VuckemDCPFu7Nwh7W|(pAA@ACwWAd3lsJmC@E<7Y>>^Ch?=q%=rg1Nkp z_oq?jww|h;i_7mC_oWt$=WH}-pE94@D|2MvMLk!_Sg((aV&28rQ{tEst7fogUk9zN zla}mOp<^4N5&3&^ouNUwr>W8VZB+KG_xPRD?6P(1#ItN)t6Z^hT9S^3Obl(jcEym@ z>dmUUB>8;*Hn+*GHEl)y+#z!559+_!%mq^B-MJP-XzTZ&{8yA=7wf&ft5pscruhYn zw1yqE7>j6oY#B|NzdB`bIr30akx243)vT<%BPVv1`huzZkIC*cS1Z)i{2CSx`AXCC zySBb(W?fT@9)Xv=blWSFxJ!`D8Ewmc5OUhA4%}G&Fu{W>?TlEUB+~9e52%0clpioR zWi3Bqn|19<=JnCOhsVG9ZuhyAf6mlh+TfEZ+VRRr;K&}?A}1N=*p;Pe~q`P?xl1O#Y<<$!g=Kq76hPDS3Vvb8z#=F*re|TiHOY(m0OZ2hk$lI5t8k;^o+#!pM zHScMux89I_*KwQbZu4A`qYsCbi4}Ro8vuaIhe^5g$e!bC?}94nnbg?{ic7xM$IiUG z{m!$_E6i_%X&{@m=r_>8s&>TX>6EPx4jY~(LwsmO9v0d<6>VYb3kB^u%ZFQb|z%Ic3n!sSs<-?WOfUiRET-dAJhAM948M0m_LyJ{2eq;uR z`+o227GEN*dbJvj3UvfXdzrtHMu^xvFsGBgk-enm$z6~DSZHT>#y?!|{m|J`k9~{> zxe(`(%2)I_M&NXmIXKTbUa&Si!QbXANG_e|E5bWGONu&$G%AqKe|=A9SJ%6q2k)!* zMpfpH;<24~schXN{XWj2J_>(_M3=@eu}G>s@EyW8F5zQkgrligMD(*!CWNy=2ETmMNR$chPG*{RW_eAwk(%LyKkkWCrl+ zT`JNZ$n5}0ki3tjWjeM<+iuUkEfyye%swjj_2aEX30=~*o5pD3;o#oghmZ$EpOOpZ z0;{N+*Dd?QRU74Y&9!q8F+#HqiGa&o_ITC&HpR&I*F~N$Dp;qrvGrn>!x>#M4nF~b zSOB1~bHQ{+kzdT)&i>Q(XR)h(-RQeyq`ekL14$scdIJ(XookccNyWKY>mZ4eak}@z zS9w}1CV=}t?lL8oL~L9u8SJxhd;aO^tzU{L^Mr}a3+NCD56E9*{g}t$W(H-qy1;@W z`KN5PkK<+YEO7H#tJiSxzeUUW)m`FYonu3~Kezo0{q`yDqvu(#7iq*MKJ~q1#$$m> zkxdSy3rGUdCjsgPib`C2#os3xI&LWMrswdJ-?QkH?VhUHUF7+Ln9~hk@^D)hI(F0H zVE-n>JClBMlqQmcW;Oq@bFXH76$q_Sir56D%f(GJg*>{m86d zk9jth_J_=~%=hDYy-r^WunSM(NvyCPkY7Ep>5*)nTNc?s94lE*3tU3y_-zIp5zKJ)1zo2XnXyVcJY)?W<(0Qb_A&t=^KL~ zwAfcwp-vpWHEBVUopIU|p~W^3S!BQV6`I#rQl9tBFxTV-2cMVdkUbCEnlikR#zXuV z(0glO#%Ic!ie=;q)g5(Bu$>j zMXw&(ii`!|;>?dmcYQVX%m+aeZ(2j>{QGCy(@I#g+BJ=4`c{DsIti^9vwQ56XIt9^dmQL>_Z7<{u z6oSmEsPjRt5LJgX?wyRR$D6rN>|zvfH7rijH?tf&t<+h}A?ygjQ;B`eP8g$A<-#9m z9@_Mf`ly*bYc3%K5&775%Ql?o}W6hIEfBjz+s^ljw5|m zx^jkkrGF9Uk8}O{vfN3bVbXc1qP-i!G19{=Yh`$@Ox4(mw-V2x6Pz)pRZ%rxNFT}c z%}YWueh}Rs%B_5Fg4b#&7P;d+~&PdD}+ zIIDerEPEj=t0ODjT!nOLVT)Cr;Ld2j)I{snjP%QEOZ5j?pZ*}jKB`WkZ0*=CnMDYxk!P2IXZGjjVA8i`j>BEs(Kr~N5Z2cLvP;f9UvNvV$$ zk}R+Jy?&e!qkAwnY?HD0LabdWPw1p5&bcEq?wE(e*s@MGE`fEB@|gd}gE2b};V-DB z`Lj>?{~*oj(Nkz`tk$Y_9&m3_=HQ<2`*e zt9Ig`dhlFuKt3Z5gar6Vq>Ik`_*@00w*a36wLU+m?DT5?$O`gIIEFOY6g@|?Em&YF zxV_h~I<&Gb3BlX})E#1dFux_WV*d`xNZLoC=3*QIT2BwdtIx`mpQJe+Iu%PM&hD{l zuc)X@!YMg4ww0`R6pv;{MrkqlkmJ7mBwC}m$Kb{SB8}OLG@C`Sx*&d3LECvS?Xk;H zRn5GvhAR7yOxW1BA6{bI@9RnsA6=FVcBzYO2b+@;pQPk_1nrx|rm=s>8};<`!t2`T zg*f0**VEf8?wiANv%p>Qx6BLb{JQs=&$9;52R1^_A?2L3V9x~EopjS<}Qk$cl|%4X9>dnp$p6Pq0~w5a-2YifZTTi1VNJg=5LWA&wA*}YcV@lZ{T z#J9;CFQnzNt&^J>ci2C6q)_OhBQxMU_E4HECcivaT+sK#JfEQZxQ|X!=KYRaeX^_Lpi`U8Ex=)|J)C2zBlX-*e*>&yYpP!n=kRjVGo7UbvZ#tzHp6Nup z_xY3Wv9ZNssAMw-=`pl`6GYISTnmgT+fMlz)q}n(67Ae*oun|iN$}(`m#OVZt5kM- z6*Ttk_;1R)&5Z77>0rylv;C`wQLg- zbIRP7IJ>{?aP!<0wx_Ce6p1c=-sfs1v@n6* zDv}WIB1wr?1O5}@lJ#?*OzM;Zru{>RE-}*H{7tgi-|5=@M*^-Uc~2eA@0wD0j(HW+ z^qh|@UZugL#64xC@0OqzrhD|+qo(1x8}*MGp0HbbXjDTBEr<2A+CBL)f_5*+KSho} z%yoHS6w6q{AykR-p+oMH!NN3)9@?Bx6TO1nZ##LUAM+uAf4ayK_1_osy?Kz^@g_i-hn;+b95s7i4utFf#iHfYcDkjd%W>yzxtpU0p zCSSzTOd%dpk9#Z7@WQO6jXmAb(eZ^not=y6#?By@4wJt3KY8Ezv(R(8BKy-=b6+mvU*%29KhFZ|h|fj50^_J^V`C32vQfZ5_xti0clOf) zh|N(DxA(n-nbVFOc>Domo1_YL3$~V?NiAE`0%i<;<3!VbKG>@%B`%IbbKFm1BLM+>c zRdBCfXkJNZBZ=0@L*3ps$+w9^uvEZ~A9G>b=#l2#G4Csgj}n$;29vWJHo38<&04sx zHnsu!fY``~w2vXPN*n@r!Wn))69G6%c4j1S2)+#o9^Dg{)rsd8`p$KZ!wvtX8==k#6diRYd^8HrC-KF7A5TDaZ# zBJtz!*MAp$KM`pKsi!7szAuG8#ljY)GPzHe*R_gcpM4cHumwe*?HMn4&Ou{n(8~FtutTu8wd z-c2B-WLg=&E7pnhb`lM$T=QvVdMy&`nVTfUIE3CW{DxC2Kao3+eu|~g%E&D*S2FtD z&C%Ykh{5k2W33zT%T){)%_E81r2(00O7`{jzbAIFC)L!Ku3a$p(la4s0CSFLA%f|hleZ8#CC0ytDZ|Sm6CtAOrE7|(`#J~D5-n(n939Thh*Cwl`tF#?!E!mz?0^;C%Pj03x_G+2%%PFWb5~=dfzDceE-G?Hwb6@V%Ty zdw&r}r?|2LKevj@ih-aIn<@>ghkrl|!KJIRzH?^*kXNWj742E`CHTk|_@vTi?B8PS zuE(%so3|O`f?;Q&&(K;Z*l?n?o5bwe_&Ylz!6U!B-krqkY=;(Y4kOPq*;C$tPQf{3 z;nB1CW@aBhdny2<8T(xX764`@9Kxqe_QZ~4xb6fb$qb_<9s9T8nm475A z87Yjx+nkQ|Tdu;tuskMtC2`6t9?^_e;s5n+WH~?cs}8v(BYK_x)AVIL?1^$E#)VJB z%(cI)0~`#^p4zfnU4&xz-Ze)`FV~bQy1<9eLY7simbtC zyFH9mIRt@CAfrAYt3=u>0i>5E3xoHgFPm^e{rAs9?Zgt@7DiiNMW}o(X**T&naZAM zoBy}y>m&$!Z$D7vfBvP#ig7>X(_S=#227e^v~oRW?+@aXd#pS1X_w}DY(bUn1Y<~ig? ze)~&F!?sDYj*)q09Nf%z7_L=hkD;$j(I3%ZO$)|XxBOy#)4N`AIp5Q-TMd0x$RQ{O zn=lsE6m}j~_Z&fnG>NnI9yFCp6I>HHHiq<-m&k*b_JuE{lBaynVpz_|k%j!7mti5w9^|5pMmJ?vzOBrp zYPQRRRfqm4Au{|E)X*O^Ab87;tVQ%4lSJR5;TU9&j{Y`A`+yel!2xoTxg5go=L;XO z6Xz#Lw086d)ut4EoXLRn?SpQn7uu%*?JP8~9LZ7E4A@~J-QDrNeLZ^~F0Q{+mrXjH z4ILEx;1EoB92kC#m&ho~2lK3&{oAT#hXY*_MvwYsLzQ-z>aCjH2A*Tb1Ttiw$%wC- zMF8`6T@EiCUXbWsow9yC{u3w#Q2n^99j(d{qC5E@Q<)+!55Bag%zpgE>JVZMe+j7B zBB?Ht+4KouiNB)Nx3?UqWnVQFof%NG^+WQ+?X3>8&C|?z$t<)_ltiGrx9qt!HmwCP zqTPVe%6!k@d?Kwjs(;2L^lGrpZArsLv`PTY@&O(zO1vyKOc|I5*JW98O-;JJ(yXR~ zg$!wBvI^w=8Y&Lmo3UY3B$?dm7)T<{ww2y^*DH?-&0jk7!V<)#-)>z1sJb!>Pm1)1%q+<$JD_PBfXR=}cwwR0t zgA;GzFu#|?oIz$AMuD~s`9%6UxKJz>V&Cp?V3qlyKb~8>M1H$>qiwf-K?|63`k+0? z>Nqk3&69~&!FI!L8uB2h+bpBRUN@2}(%ewC~+x8tbb@aY@FS(%lQ~!Ufw~*}| z!h9jhTF)VjhC6TwD>;Pe*!0yKEl+l}xVdr&f=}Uwu*F^kxMyoSwmsi zgr}ixac>ll7jg*WUMM4Xtm)AK`0CvTs9gMRH%@zkF0xTNi0Q~#8xG-38~88t*aS-# zIS#=kF5?QO$039qLKnAxcmzQ=!h-KR!FtX6v|%r8sb`u16oc~u2U3U_;($G_!VXZT z)8!05R<^|bKt|ufpaT~HU=b2q{5-7kIrEaTKm|SQ7j`ZB_Tma=P7de0lpHuaOV@#93PBRdjek{&7zJZfFn%{fHq0Kt|_!*6k)^WBt>`fIR(x zS68tcmQLmnPSwF55tLD&aIH|x1G--iJT@Y62%>{7PEL+EAYzK>JD>>k08Q7#8%l4e z$5cTYggJx_F!DnL%Z4xP0_!&P?ER}S$Nkaky!2us_Sgzxm2(I&9Kv_#f{T(E!shdW z4uUy^yYFq$H(kZRKVZuoUlmsQ0mcFEH*e>gcjs9sB=-qFQtbww3Ol0jFEoQMPp`tD zX_O15!|jek82%Cc-pL8r^8N2FTR;bZj#3c$XYY2+3uzbiW8CyuU#=x1GXR^i^PoAx zD)vNyOP^;zjB1H9fYDg+zr;n!{2Y+tpuMgqv_C)Y^1Q3~NI{4W%ssFKGGuHxRI?dP z(eF<$|{9>XdQ;pi?<*l*j3i@=*%xNdK84rT*@ClJQTXK}W~nL4!=`#Ld|TovQj zP5V#p8Q~D#!;sB5XtNq9VS44ScPR&?&c@&A474q>3O^87B!>J} zL>Zf#Hs7xNAZ)JiTwc4&%r7=)w|#__=-3qIvdZbUsEnMn*zwL~76497P)&q{o$kG+ z^P&Pa(eiSY3H2&uHuBfat`M`^vbEBe>r8ZLwn<)~I19C)CcpD^0vLev-zZ~6AP)!} z5bO?o=4XY0A>gXSZIo?UeCA0@*ziEk9wEk0<9b$;jZSFcs^SBeU-8C0=}`{m5K=4K zMT%dT{3~Dcb#>g&N8fW4!^1RRI;>XR^i4Ne=gx+Vj@13>SAzCmesa9RcryH{t*y2# zSnFB@`x{2%jYe4iYQC;<1c4cKQ$gwdXs77EV)o;$8Nb{(gf{0Hpqwz+24Im*(<5bj zg@!rHzl`gw(S}FLUsjkFo-^;tby5Tw`fYEs@|j{+H%TP;U$x{CJ29X8;d0sWo=IL^ za}e*80pj#~!0>~LC*#cyY$PvI-QyKx|Jm!K+|<0Z>3P2_O{UkO>u$w+gyb?j13hVs0rIOi>dD`mxvH z>p}l2pFBfZo1JT&3W?ZCbet-2An?9?<=*`#jfdKzJT?J}CtMv(qpjA+u4&Z}S~O`= zO_;mt&J!UieDwL-A7pyRK>$oWva+{okVE+Kw}a54K>39Yc{@&p`d+O#6x-P0XXE4z zRbILohw!r)(;+iK(HjA(DvX~)sII~;qYUli90G2l0LOqR4q>C!aQ@=OyzuB3x&mNA z6^)k+NImGOp3UQ|yEbo2a}1UhZ?a1bA4-!to~AA@VpPvQ`c0tts3ZKmldHDATcD*} zb{enT?e89M_VVX10jXpewgjZB?-viFJ--eXUvbm__O=DR7AJ7=uSaK^K~`W4@Uzp# z_lglr8)YOY9&o^T#1PhlO0*`dW23LG#PCN?>e*nJlNx)um}BmpH!#2(U%Q%D>UOQx zx(-cbq(YJI`mh+8wI=&f^?_P5g@Azu;_zmVxrjzQbw zHt**U);0}fABVOE7H5_nwQQ{$pW_e?7lok=70|)RoFw|TXhOp&qgvs z2kuFMWkd$Sq-OC#htq&n?ObtDaZynbE{X0yMIAC-PS@fi81vDS==979WCr|3q(T+8 zvZz201H_iKyePN6@bH-q!g>a-Obi*v{RH$4vg^PU<}^F{Mnn~{0wD5DYmqzGb_)2(!oI5#kZH<&-u z#FZoqkh>{1gcTR4pa39nf&l!@eAW*Vhj8q5a(doVz~Avj?N zeACR&x(fJ3JV*yZ9?uD`0JU>YpPZ>|Q#_uUE^H5}>TmD?(6dxM8{8-NQuGmEKfm(} zCbA#8XaT=v2;~1)h(plTxS@J>FCYdZhAE=-_s;d~N63O~`hCa@o9O`LRs~?GLY)^N zRH@p`k}ZmtxF2C32PUIcvKL4_D^&+ZaWSll2DcjXbHx<(*oNz!o7pI9FYY`HA0gAu z6f8Qd-2w=xBb7ez0jt7JE_r2~Oi_SbTWTHfWKTSf`!3d9h3ikzQLrN$kfGzLO)eRm z-&TI!WU(1c)ffdk$PMX8OyYtp`tHS4IS65i(bC9y;__ zD{jW=3G^yllI~;@>k%G^K$}1RL$H(9e^5ff;{AW;ldU0Ka30h#QB{{0Ny@>Mr3T2_#2Pz6W7R<7@|r|97bW zci{i`lZqDz@a(`_oDNzh3J#1^0OXz-hp;M8&}=ovt8i)aXR~+;b`9*^imxB7>)BIW zLna68m2H7=Mh1^^&6*H4VH9Bz3Q2V00vFGvzzaADUsDcvwE!MJG=M5eXiKF65N-vq zXg{{1=ZCPKO-^-_9mt2!A|R>_{nru~6rAhAy7ED!&ol*qC?=HR9wQj^^ta$H003Rg z07{~4mjmuN{MP|!;1cz!brp@ml0X;9iygN&#!nXOhgJQ??HsJD4hKO^@dhwtUYsfQ zw1n_xaS-GutPcLR3|E2p;-r`>x8M*yMz{jL(>g)`CLXs9fvn6SY%3MuG=0lCXz{bD zWS|t}lS5!d0pJFyX^FnjkOxASN8&(AUFcmV?n6^}36ZYqWsQQagO+m$d%SwkhCL{I znK`$%D+-v(^I8!T=M9?CZ}}*iB&W z@Oj)Z-juobG@%R~IRL$U(bB^xv&ewePLv*a_8iWkonrF0V|!$)_o_U266=$;5nJ&A zdH_`hD%E0jmgY;Y>MA$xh4aP8T&<9*0$;KyQP8GZ4s75M)V%60f)t?am3c(W?F8^n zSW~_OXr)E<&1~S`t|Z7W6I* zzN-dUi8B?(abPs$(M5oB+ZRypbfspezj>LE?0% zHM+Ri)g3t=EaHYW;pQ#I4FVDpL@U6!umdQIABOxJ92pB`^TVS`>crnvY_|hL)CGV! zv7&{D8Bn45DoZT@Yp=u!v#?;*>jrb5U#Zl>?bUHee~QWK>MyHE=uE*kbWs|`jBsmO z_*YoftOOBThx-sMLoqVM4aO7*78j-J@XY+DF%AS3@n2l zhF}{qA@Om(`voooz5&61co2WfqV-rD%1W{UTb~<*u!`b=E4{K0ttgn;RSWDSaYo7w zd#!h^P!M6s&!iu;|I6~1Yvq(uCG-`7E=r*T2rCAA(|aA%4x-~l;LO`*77<&Ot9TOq z2scG4^1*toCe9S0^c!E`+g~8}e!W2X8dWeb1IWTrz&PV82=e>rw^QN!6Tkqkhg(2S zkUlE|bdk^Lq!K_YIzXB2ul!333p$ju%LC-a%*TA1Lx@lwj;4BTm%T&508eKR907Wu z2(Z21s|y)gf~gbN<48 zXMiA6j}Rkwed=VMxK@CJ|N3A^xcU}R^;fG z1(|Z7MhN=5ymAu4yYjg;GPgUJb_EIc$&4&J$qG_<-vj|%R zFxil785>(!!cF_8uUxg-#UVu7i)2jOBa7wPZu}xof+o1ocC}%bjAE|d<3Ak26p`_CBN!ub4&f?Vi-m&(hJdyT0nA{I z6DXKANQ-1If@uM`gmj2v;903sP#RhD01(N|s(i#*c|CS$AxI$5m#Tw<->|N{!_BCb zvTz*wfngi&2g>DbNdBU&lx?~8m+IY)cp%Jdx_h{KZuE5i-bIA91-EcA&48M)3nrML z7?S$|!K6)6pV++p*z_=SW1=)~Gh>&;K}!RGc{4xD)e*YRLopt#3>k!R0~OIl7YIRv zu{BoUaiei)slXN@#siE2bin#Wf%Cx>5bPEayN!0Hf4CUv`2e0wKx_1%Y9S6>912s8 z?FuV9G-&(uU<#Qfe%_5ksCx@(&!W;uf^gsugJS4%qz!I@@sz%Z=?uI8kbmeXfE4_~ z4z|{zKSfS=bUac}&u6%!Q>#Bf^8;QTFkJx9#^4zY?hoD_1PG51F|A)%JTf{Q3q1A) z^6_94%+9!#%<@pQfZD?@U_%ysWv2s@#4Bgl1}G^YBc(YL#cp-yKcwZJ0nV&4&J%gt z_}=IO6=)C!&FSe^FdhBWSzGx0I9R08!+|M=Vk)AEP2n4%gFpzSKyQFaAiOI{V0ln1 zxE4Ti_>H#Jxx;W^F=l~KgNj1z;c}=Op^TI0q7Xv_570sYPaRMd34rhY{lMK%4F>M$ z2p+rL&%!iVXZZwVw6R2gkVQ+Bi{{cvCWXL zG&1b>^bUulC+J@S`2*-Lk{8h~gtZb#CWK(A6gF`lpnLNmr`*jD1Pkpf1dhDj3B#Ft z;htuGy%rX@%Q+vJrjo!Q*2bcAUW46FH42@*@-5|{SwHgAVa{RZTHdBgonZh9csXc% zxDrS@B&KK{0g4y`IgbN_2sY=QM;$Vh&w>cGDdA2bi4kK!rUMy2P=F@Wr}L3PgY(x= zM!3TQ`Wo)cNTvfB5fIyh#b?sF*3b#s?Sh>d0_ginMZs_qTO^a^Sve&H4*w^{yCi`I z7lBli`QeutCz=jgug{9Xc7sX7E>?n%gG2yuY`OOD>i2q>^dQz##nJ-{5Dh@w!HZ*c ze}k|AABr*JtZY3i6?Sl0V8F!GU@#8Q!E@vn@HiB504Y3GSXnIMQM#RqU|X&CLSbB_ z(7B=M0t)=+RRq&F2k}CD_*sx#xn|IfJrduGiE|X|tD!is(E5VhY-h^Au zctuO{qOdn4bnEd#$l@LcFxUB5>I?~VSLuXQ6Ewp4CyY_1iy=%r)69mX9A)^(H4(9+ zrUjF=`4Ie>*FAjtbE9|$9$6ZB0W$OYdYFdDx07+eIy@3u){IY%%tBS6rU7hHVFD=7 zTlC#9-S$I`e)%ywx$BSxUNwiPkH!1%?fO3Y#;8}hM6s=klBS7hEp(U#JrC8A7SZ3I z=V7xPw^{&XJqX%|gBJsK4=D2+XE~-!!D7xfv&UxBFC#3z*h1b-MYbG5`o5>%ywQeF z5yzix*3kk$%E8~JDTBbAaIP@|6N!V#Asj+kx1ZHwphatprEL|FS-dFlU4XQB_GN`R z@}myq=*QL8c!YH#P<2)9>49tz4eu_9a{wat#nrhKI&Msm@7+?(fE88ZVZ+?Aj_|;QveV6r6b2Ox#(q!~ z(BvXy+A~l3s(}J&Q4ZqL*CiGX9Kt$}dR7$_^8W>+^1RT|bsf0f@Ad4BfzZSS`h62G zw0L!7jpgyeYtRL-V2{c~_yOQ_Egs~5!AJn>G6Y+JLSUku$wC3pAqbW~dO)xuh_b@# z;IU~UM);s+4vA{jqE}aC7n!bNw^`|oSA1MIGCzbelEFLZMjSX~QD}D&WDwHU4BXfV zbk+R;2-kGwiGncpBmF>#eD&AqscS{hdXR)gH#TK4aJ`?{5&0XYd-?=7fl1%XhNxk& z7sa+iiY^P@J)cEc08@v|yMZ9efsddkIbiz}P{wKi)LsFkaZC=6u3pD|zz#tQCEo=~ z7cQhA41fUjLrEeY_Ml}s%L4;2LF-j}5uh<>-kj43_;z+xHa=fcjn*_X!{$7C6;1GH z@WFLz%l#HV(UL8#2gQxhMKS4*PYj`t`nPkiZ+V3cwgxYwMcl{EXF_K`G5&J_fF78O zA>2~YZ{TBylOP5DL%vMbDxhW((BQkl4-P>+eJA?v=_7@vgqrx8(}j9X3s&DQ?gceo zCgu_*U@aAA1$JZ^fYr$BH3)WBT8;ul49$4A@je?bF;*8k54<&Bd&$9J*8Q1;@>)d- zwj#o{>5M&s9od)&$`GTc5cZROt61#+BkRxOp?tr`aeNe6B4jHqBiT(+*(!BYNs;VZ zWI{+Ol@vv{6hb0GQAXB~y;R6#FVa*JDvd2fH5ki`nYsI(+w=AQ{Qmeo9?z#3_kFIj zpL3mat_z+QC?ni$#3^Jx3fPBmKRs|mF;J%u8F-ewrWw%bcTBzlTHlRb`bThcq;SQG z{t>(?^|Xl7zVX~xsk4m^;4EehEN<$(`x4N#=YgI~e#cu8;|~0*H-S>c{_|l?aSl@=%62ivbV5A8+ODr_7Tljoh~W`E@1#u)I_pMZ7Bh zrWR!_#kO~v)4A%F>{Z}=p8SzYTNVXD05^w_cdeNSR_d@x0%{{Xn{2hH|r+%f)SRr$MGRb^7( z*ooL(NewBZc6$d)qHdT3`o0WpbYu3)l|m}^rq&mr?;=hjzlbx|hn?ZPTLk1Er7|jw z7fNcy%&TR7kO7UGJ*40Y;*_R_%&c3s7+t4;$OO+lx%S81xD|q6N`|-{QCR#AMaW#5 zqy5gD-*|0iVA;d}%BaSmDGKPqwJokd*)=T@ltyK5F&}{lHFxsIN##|qGBiXH_0?SdE({n z3Po*?=jpP`m&dbK*d^Aj5&PO=b?d((8>smAACJ|WchJF{j*e=;4q^q$b=3ksOIwvR zlK&Bw=|0C4V{F^uNnyZwEFYA7`y=?q0=&)81o%0?h!y+nC&Jy=3p5Km=TtODSf{I+ zYr{TACQ?>VzAq@=IS*ZMcIeQrw~t&S@+6Yt5oZ>s+7G_FGYyoO20Xg)!&X2)tF3)c zSB=hG__vte+;M z;y_nLY9s@=>jm#gd?6e3iN+=!=+QZuCpz@TdzB3rc&1_Sxoc(73$wW~CH(xkHf2 zEY|keN@y3Zf8H;B+fGaF@pHTmO)NHKzreEph%a&TgXIA?RW3iiX_#!~;j)C4CJYv# zd|U&1)v?RDgaPzLrSjm_X-hC)J@4kUEl-8#9wQ^WvP*EpnO)IeQ_S`}h&yfY>gf|O zjt&YIE{J=i;!X<@(8~J>c>=1i6$9}9d1!bpeI^M6^bWOR&FU!+ToI<}M+@WRufwvAjiI`}l#x%=(r(ysJ3YuVXgG9^~ zgeULx@`=$$>VQUhxs#<#FTj3_t02zvvd`&2BaqYzy9&-S^~G|og~#1jZaAG0kd9HX zn=ACzA)~^zjeDAqX+lgqZb)~K8Rd39k07ANNb+b~tiUC$e*_A$=vyU#bH7@lt|6?p zd<`;{qn2)OXy;wEIQuXV&$5I9E+|UOGu$l8@u>tn%AgCqC>Nv!B~=07Vc9FU2^t_! zgh3>qG5T=eWKdqg>C`A}g{-*r5_!lYfKjPp_tC+n9p=qaX-h=Xd_gP9;8g`CdBIHT zX+Lpp$#{bL2&e(Rm*^j$PD#2}5+_~o#u+{h(GRBaIs&MNu&{t6BZfp|eI7-dEMBcvKQrZJ%aGVg;jMD(||#~5ui8wD+2GVg<3 zaRbSLErO1~>mYxKT#eFDum;kWgZ&vdt7vxkld<*Vu;f7idcy#G33X^21ef4fKMyPx zg2F7N@l_v%zk_AQ1kho4PC~sHo#+4^l1bkw{WMB%BL;pSx(DEJ({-b`NACaE#0T9G zgXM5eE(cnZMuBnC=bz&Bh^5Vc3v~|KfF>W5*9D$k+eFr4L0C`(7SzAi03knuJZX_Y zk>Fx<$kAU!7j4e>I+9rgj7W!0&J$$((1%4IhH@mNO+hP4p(YLa>o6POm`ZPj#2|`@ z31T~_!%&I;wO3{>5J2QGLv+F8AMv8FUz2Fa9Kz!R%y54d5nK$)vfWJ@8SzJ_9Y_bA zkg1IUIMZf5F>$USH=aYpnwp{H4jYxptc+8ZKn8?6&B|j=@lYkx7{~;U3?!XwyW?(( z9g=dTV#nc;1h6ZZ0|R!K$c#M8^+(u(TpG`tB;7oUb)?Wh=jog!i^)jOqrI>hTM1ZB zN}qq=Mut7kq&}537tj5JaBreKxcE_A5Bg62p&zq#UJDymHkra2PgDL=G@I8!Cr=E|{4H>AN$+Tje9Y-T9SQy57mRvLulj&?ieC z5!(RDqXyu?dcQ;*%iz(IHDn^#!?Sf$3&Uz^KzH)M-~L7vFbIu8_gAbC`8H2tWMH zbw+us;hXEQ-Dw5y6aOEilO!8hTNv;tD+jZQv4ZdN5zHLiT3D`@7P}Esg{|vy0aNZd z3g!$u4+L{M2aA}uQSs_o2j1V91PC4<&ETs7_}8V2uObX6LbFiZDUGX0K?xMJYv$rJ zcym3B|GC*Ok^%7c#JPd%5&$T_jZI+fM06oR-SQt{EewpAuPV~wuJ)sWjyx+yMu58Y zr~VOKQD{^}_>O`S;cw~S_-lh^>XWe(FdSz9?%{K!@ny(RVa0o2p2Anf^QAoD0`Y%@ zyJ)@H6i9?%3tJASM>xvBhS~N1_ud127CQWcj3q)jUY`ilWAILx56aEP9%wBVT=Dm8 zKx5x)0<%z_uDT`EsDQL_Hw1Q;aR~Peg4yYwKJo+v4)at4fTbC{)9Xg%?T-U=Lr|WL zLdWmThA6ukWH~<7bV% zPllP;pzNkc@H!Pr=Xm>Fw71d}6DZ}5l7Z!5rnkv600FPSa@GJpt^p6YxLnz-pzxmX zzh0Fl0~7(WqJM-maQEm3Cy--4W`QebWiW(wKqw}8F{=_mS%TyRU{Tuxlm&}fShBSK zgX9BFF?Pkouj8+l&z%9V?{HKW6No9wq%5$gA23exhL-pY6q<&BWx{1;uuwcQ3GC@W zG4N{bL~I$T#Y`%&8njm#Y!{RlZ)Ea2m0yAd6#oDrZ%NJJDi35k<6c~f1ylG z*UF7-bO&#!IDR-uhPZ9KhSMSml&f!L}v<1wVy> z?rDe zR`v#14@P?|j6b$0+z$1FhJ~?|<>Td|);k^tcy%OIA-`3*BMkw@XUqMZg38_1k`>9U zeHJ&fn<2t71)&}=Jp>|nqlK`5zU=+DXIXS;0w{MW=uW!~-tSIVPQ+&tZVmu0$e)qt z@r&tM6nEOmRnN8LLLLD!gdHbh&iSFVSdgLZz_AU!X+?4<(^8|drrxFv%t^iEjBLU4 zvkqcs)g&FUwI7>NhNquKdWH!>#+S@G`^jtT6II-FS+)+g7!D@omKpe{xVtkoRn8i)=HDD-$T&eXjaSP`)7=}0e<{071w=4Tf{TyMv{&?NNKiP$B039R|P?tVX$!{Ca**L_IaVu$1NlQIQg`+?%0 z+tF4~%59*JjT$c@mob4fJu?M-4PUYz1(!t%u(28C+Iqipwolsv#ez;efBOHer$z#Q zK!jo@P-KAq+Gomrf5asJk~su@Tg)WM#{qDFO&x5bVIhd<(ZCK+_Tki27(I|ecsIL} z{G}~So*7?&byn}ubnTfe5WAO4gC~iw{!G010?IO^{{Fa_%;r)tqjQHpJUyeTvlV5< zO2;lQ%!Pj!w>@|85j>%q#gbPKV;aAcUHr2*EcJ7E!aueY%@BIi(j-C2G*Bd z1G(c8d5YJWn_x<)e! zgMjqy)bReiCvRf_=*Ae7CDt67g)aKSaY&()062hdJq2I^$m>PLx={`jVa?`5=9#_< zK&mUeraS{6*MDs{wzij~ z>__Fw%gUntAt?J3T0b~degycY4I(cvDbYD`>Om1K(ryxC3lT*R9drN`lPNq0^ld5l z2_RJi*!muj1cZSn9x?eoK3+aP!57EU7q#IwNsNIE#_}f)9PW9vzneszLMDJe*l84V zMSFw0vBBn(2oLNNXz9O^&)rz%@c=}-B#NgF+Gz?#IaeD9fR%u9_$OTDJ&bdJh!**G zA$JebZ&&X1gmhX3L~j7)2B%jRznpS3U-)&XeFYVFf$4t5CJ+ut>Sq)$^&u?Y7{dex zeO&Cjw1D6fldSI8*`%wc?`~*D{=%}}z_jThNXKOGI>KVYhHGI0$`uUsz$A#8dVT%dMo$efmjK2vDf0R)JMl3 zvJXH4S9l7-6xn<1^kk2S%awG#lS<{-UoFM0rgRZx3)uz z72&Gl`X0MeA8YdS1BD7JTSAcK@H=~aS^{zvE}1#3PCvSC(NfLuiG z;x44A69aLpbo@N@xdTe;8~pU4-2^f1HkE4xGNNE|@a}<55$F5k9uVrTv`7|5M%LyQK?)FbOCpL4QT&Q3Oikkb-lw;Is$$rjFSR75fA$;m>eQwtAGQ; z(jYks*0^WNdONrheSC0CoFz*FCOw5@n>_g$?P(S+AWnNA!!IiBI&~CF7ITGR2n|!} zx_vMfLmh{>K-SY@H>CJkc)C}>;%vY!%fh{!i0_<&5w7wmcq(-WnSRla-*((`GCQ6% ze!~$n2TAH&ywRK4^SS5uw>@eUmb!y)M>Hs)9?8Vk6AQ?PPVM4WZ{26J^k4wcf8`(H z@}lqPM|g6TSRwkR1gHSs|C;U{Ct}x{K`ms#yG%p+352>2#%UE*SDRfw+Jo=t-_+!t zbTP4H$3So&IG?ZMF$_dM_?(TwqY7^UJo0m|nB<~m)9}x7Vcu-!;GPGcFOlK&zDWv8 z!xX_Tp)jWq{Qs8l5W57$LKA(dD|p^X(vrcqj&Xmdvuo7BT5hFy9R^_pnD3`?(<(u- zwt&S-N6LbA%-rp9SVA1k2^9O+Mk?&hl;1B0dCY2Rv71nKD`nvn4U7!l==oc;)3e;1 zx{#u7oQ>T8;l%xYd}d;G1;T6qVxQw|PNB>e0sKzLdL=+al}B9}Vrknz!gNq$ZD&}@ z!Cemo&vbRZZ-YP*3$@&h0QyqQ${)z!u~PK!#m3{#s|y!{Ve$4tE%_Bc@-cz7oxmyp zpBw`&sgwuxUmqBDDk^k`t;2s_d=NnI+g>T)1sOZwn`=RVF3oZ&FlM!qq7+{rKnNuF z`()c-!!0|LNZ^h(o{g-LL52>a!*+ggH8v2(4bp5=U^X{#ez8252nzI?$XZj>$|d4m z<|dUqAbQ3iUw6%-ALvroGZ%#U?8Wh?-z2Bc+4eU0jxXh@xsMl=rixX$03pm``5IS} zH_8G%vebj;U+ew|&WDlpWp-PwwaeaBL%&CXUm4cVlAgyMJWW^mUm-dB;)h76ek1~yLSpa&N z0^^4Z{OE$b^U1wnf6cJvUeX*RyIddw0t)+JMVeK`P3N_}!fI1C;D>3jec2xT5)|-j zPAwPt2o(<$rlIvnvf)~!Lb0OUfg|mn*nH6Ej)!vG?^MR(62NiRa$U5k*123)3KRO$ z5pAQV_{NdUmI?x6!aG0Uu^X|%JUoZljqr?>0riC~xHX#?uTTRdH?|=o8q5*#HXxgP({2UuX7Eu!BH>$`fN9?|kmy zfCESaRCbM?s^8WM(zlk_W_>J1sazWB-C&(7d;ypAAI<>5B27;vH&)hzGTA?z_Tv;7 z)KfjYwvDGrZ*lw!78@NmR6!g|PDFtvT7oK>E5RdiF1lz7!d;GOf|rl3%nE_6ubvOK z)~?SMQ|!06pM@}_^L2)xJOZdq`NGZ&@<)6)X7WY~w45y-njSl}M!C*kxb*CZln2Y-r?_!`_1BQES0B|@y!xqI& z`)?yNh;l^%?xFvKTduaKJJaoWZZ!a}L7@NeRiWbCadcs&s@Cl+l)Vk&H6XeO*#}SM zK+79oYXk=a7k>iq*NM~e2zK`$;s1Ey0oZnE>YW0^F6HV#QgZHj`|+S!Em(T5>?03^ zXNye!w|%z;odsHcIf4R+FD7eqM|Du{>*j+vpA{MErBH}&`Vdq|0xmp`hoas#GN-x$ zPHOJO@cL4YJlGhBX&B$@%oz`16xc|DK;Y@ux}Xtp_z8pkvUR$E>|+rb5>$OG$Q)&X zWq3W#o{Zh4VlgON@E@VV7aS^9g>tvSlQ8km?oI~vhi+WQktiN4F!RwY$#!wuw*viD ziqAjHgtz`9RP90Wno=Vu^j{QeEB8p=jowLn)aRc?J3O8;iq-k9n#E^C7tnW z8*2V+3W-0jx7=OC>n?fXXqzZ9&mhsBXb3B@m>I!CYq#*u zU?35CaaA`qF>!eEY-4R5Qp=<5r~a*}$afcG6B~oHUlj zA)7F1YRr*RPTwf|xFM6K!<0&y@j7z#O@-Xx`Oo7;PMM{rxp6n}gSH^C?b#KLjNQzh zK_O)wCas!X6yIqUK1hlLpB9|-n~)a^pBheeoIi20M2?L9BhW(ty6wB7Us-Oa4pvNA zR=iF!&R~=pwkvAyp**X4htZAs*Z(8TfAEsoyEbeCtji?&HX1;fmwGcg5`Fx%pGTkJ;^LJtU#&Fj@IsXTj{a^XF6b+L(g0CjH z*DrKW^ceHY`Obf+*U!>nH$&J*ssk8x97YL~QNbBln;>>m{+hkOT<`H=Gm? z;>Tw+W4>9aL?;xNBr&R3qhhfebY7=)oUbV9>z|fCvE&DhrsP{FE@7+>y!&9BXI?iU z@Z!4Z)CA)yhf&95?D*!}o6wb0cBcB&7%$+RfkOLACXGNK=#n1aJVv;(rO9b0AVGUf z&~|Yy&+8o#f8#z=wf=7Q){V#W50y%9p@8Uf^d{_3sqhU_sHt6vzC@svqZI+4w| z@cE6-+r0auM@KtI;e4VEVuk@R1O-YpOrORjs$BV-!U503XMbV5K5Rnuw%G6Yd(y*J zx>6j$HR7<^Ht7(^bogh3=f*?n6g$ z#1oF1T(WQ9YxBOipzF2lO_IV!+E$U#9N(X5@`Eq^T%2=_bv&0U)?la?ll@lNrTA|DL+Y?8Q z=B(0v{v*&dBUmu`&`gH)h||6o8+OgVGUkT^gXgbCCFp$aZ(Toni*I@Dw1-B_wa?Q9 zNjualc6J9^yX=;*Bn<4Q`719%rtkbMX+J$w%V88!N1ZQyvhubKwWq7|_XXJ}8g~<& zO&?gloXBzfU@S-H9KJM^MR>|@!udU_m82?UeOmO*lBKjIRrF!v<4Jo{@{T29g#GJ6 zP2@uz>7h^*SZEGP24&(5r<}dESJ%ooQraZ-U7(<-aY~ZTaObW}^Wc2TcoB)v?r%eK zwmY78)MZ)|-@BG4ywSMRZosEN>1znj4jUU^ADS$-_Kv8KD8H`q)~>D}8!t1`sxx0P zGsA^Et94V~+TExvQ+T5{dk8d=*fN}VH0 z0jGDr+nExx$#v&?gA`qVr=moUpK3}U>_68{jMAk!jOxpU4_OMgw--N}vpapLUUY5? z&D0V%EBwEAU;)BQT_i8?j?U3}_TlQq^mF8^5I^XFq*)^pXuh%J8_1+2M`*Uhc zi*=r%^v9}uD1auHD2swS$jp1Zp>CpK%f+6z`n28CvzUs6_G^9xJ|O_Brrm1TFKojN z3vGs$3F0E8J6iUGvere->T=_%?7Hi9&sq(28xD!sAFH;heYD!4OZrh_S1Mio^UakQ z17j&(d#uXkWSlzF8Nyt?RWWJ&AnDMy1|bE40^uE>K*aWzy-E*f0_VA%@4jvL!l*-Z zFPKZQABkM>u44XhV0%5g{qDi0Pf`2SAKkRst1y#d+(ln!xjII8Q{tNquY|N9B1Jwc zr5d(hYvNH$mv7)p=`-w1IK;drHWFj3bMH|5to?i{G&tvf_q@wDtw{Tl>g~zeK9<#QNqK6@kwRKmHOPH`L%5YT-M241y*!-v z9sU~YjSvAj>js+eGU9zgc%Xyplt5_2vc#$#>l7H=!DBr%?&YSp55>}r>Z;0eyIr#1 z?@m+_(@mil3tDLpTPNOA&JgnN6V@utb3R>SW4Pr)mW}eQG^LU(%iz=`<_e+g5_GqH;@4AIkqPh;wW8wx+#H%B!R((8wV1KRG=fplc z$HcbW(FiuJA~gQ{*(i&^S7|YKe?FNwd&Ui|i77nHd`b@Vnb~(PJmzF(xP0y{TSivO zJ)gkuFYO>~Zi=ZsmQnCaqV*w4@~wMZ9{E;3GceGY`1Mqd1ZDJ3!@Z)4O%?Hj`ezOs zgbkn4T9uV5bXngaVDP&(XQ-L9EaM9AQs|P#WkmxqE2f7Q zaHP&ZV=hTd{i17d)2z|b^6&*l#Y}M~q#`$zk~bK&TO$wd?!!**1Q+&KT{_`P(@QL< z-|&LVfjn(f{+FRYzSn*nDjO?$XY|G1MB#Z``ING3VsK-O^W0y>tW@#KEz9;@kb8en zu*!(dhl^c7nbLxKhNGC8Ok$=iI%Gx5dE8Y3bTAkP;AjYC5N)H zRX2PNbi<5*lq zO-cJ$RrOm>wPI@4h8tQz%o=tTM3emB&xluCjm!y^zFrx*5RXEvY;Q`mbC&d!W~6RD{RI6} z9Fl0+yspa5-sqD%niDo_6<8{?yTWJH=P!qTUbT7uY(a1BQd4?pm5X6Tr_Q66sve~c z<`W)L$$P@a2Bf8}_i9I~ZXMcDj6zf>YxVT~jOh=(%#A<5l< zH($$X59~iG8+&NAy`zzbsloLIh4W9D`Vjfah9emY!pQAOg>|R?Cb?|uyXkL6e$kc9 z|7*kRD+c1BEPB<@ucE=SWi#OGMxpT+mN(8<%zS(lR_p+G&(O7MeiAR|M{ z@2%jgmh5C6n;fdQ>)Qy=Of2Q#4^H<}?Ric--^%r8H}8&nqd(p5bK4TGNX+9Z?a?1X z5{ymTw@Y@P;4lndC=-g%EJ?@5Z=M92lvyJZ!b`||-B0z<88NFh`%IE}bIgTop4Vrp z=b!rrPRSrXtl7UG=X>+YJAagzmpm~j&A89VgUTAi&yI=gYJ5#N*m_T__4|I{=$P`O z<&1^;h$2NkzM7K^?TUIut(R95I{YW91O@K9VMFh*H{s9^06%?L&nt&_rDM%(>WB8n z=-mlJmo=sIHqQ(W= zxFKP4Z;f^pL+uLL>@315dBrtEgY#as?!IcR?56bIkS*Jp)XU4-j?G`8qfez8E&c0Q z${1tU#Gx5FKS5U}@u*{$!!Je_iEwufeNgdz_&q|=>H>r1Th6~M>E9VWY_Nu8iMCqr z>c(Dus$18*Y@QzX<%f((R`j-1x_kD!fs&@9)|cqKdC0YNiffreRZ!!C1`ntEgn%!} z!K>cZ0Wun)4Qeioy(?Fz9T0kYIx$byCUU@IzI$tW+G?aKct@q{H*9h+uH&Gnb4T8H z2cL7F2&dP2l53*_Z=*j#kN*g4A@b%v>|!!XoagApXrqE)?QdFo&t% z@9{#6?789{uf(e+I+n&lFK}4HA^QEQd9pbr#N5I>u)EWuS>E*;`*ceWZ?5O4=O|R$ zq%3qUh3b5;ztjaA3tFAaIQ2c!cWNv*`AF}YME*&zoA+7o&y_+Na_$-gk zCg>koXT7HH^lb8-$>voQ52~b);brO+q;z;DDiJ!D5DLl`{OsF`9gT)}>d({Nue*8| zF{&Zgh(pix3!d@4b?(^vx&r^Y2}TCzz0%u@JBGWZ^^b0vuHU*&<>x=B|q$dH5z7U|;+eIwJ$$++7G9T2TfwN?&))(@zg{ z2E>jfa(+Ks$jz6P)O1;Sf#X{jq*XiJnt_t4=8k>uW7J)_TwA34^NLpek0ZeXe?C^m zm~gbl&adD7H50(We^9%ihu$EDGTU~u(TNOzJ@gPhzVNBrLr7tXk-|ro)~MZA-YMtL z^2!Rt<~A_eCN@*HOnshXMT9On~fa>=yQ@s z0eY|?>}ucC6;OwM)X|=IpVLPyb~LydD1-?qKHA{_!_D=+LG`aWJ8Z>^Wci%G8=k$8 z9T8?y-UgB_2k*T4abYUtVL)QtsrL6(!o!m?CUwv)f{jXOj?C%jKa4NYL#Lu@i%^=M zHfKNa=%w%6@b{(P)gslh3c~#3C#kFA$In!$eI24ayEpyPDLp*R{gm@YCRe^-i>*c8 zkjCX_wi-K~pYF|5%efV0S@-1Zx%nUG_=%zOUoGb8yCyAnOD#}~s~Yux1kR@L9QEUi zS9RY0@ko;~x-n^;{Nvoxz!-UUWxt}j$cMFWlupKaa$NV9Y+QXZS)3b0zjSNsiL!4N zD>852c}JyI8w*O{*v`p>FzF$Uw8HJ6AX*FEdkLE27-!#m;i~LIc6Qb-4BA$r^4C)p zmq|SmYj-(z=-4h(eKy@2-?uXXF8JcU9FzLEDx&#v39 z-gZ!VkJ6_@N&=}J+lJDKsW|Xo#V_hVX_6T{oe#i_V16jpv=P`wsbl^_Vj;{&{jsjv zBPT^G7#&-gy--d2M>xqQ9vlwJx>=ewJ{_?8tG#H(iuT>4_g_VO4>3!(wkw`@_WNDu zjaN7fAB{3R+iLKaa3!3j8$($vl=*u1f&lf_#qQlZz6A}{ot#)NpOscvkp4-s4~z<~t?^$bPAMup<-Ws~p?y&Qu7tnE-3mvs)+(dBH%az7GKPWoj>J6ea zhSJAiL~Q}12xZaUu@|nKNYgw)i}j8Te|(6s;nDJMSZ1RSD{rK_fqMF!ik)FTK*g|PfcBRo@t&A7S*I#VybgTGywe$GaN85fmWL=)P?s~&P zddpfPsa5+O?VdvENEeTBdy2eB8E1^5uqoJLmK2ipI8e_Vv7f zp&0Rkcp}RthFOxb1KMQXEu@OBVYdsn-X|2>L}eY#^ZQf9?O*%lz1_wd^$EJ+)J9r; zObU*+1Z=Q(Go|V{Z&Jn-DvwfWHLQePx#6{n?+cz$j=mDvsg-hyezi@a)w}SnlZDB* zp-|pO_hl*ZMKr0*$<#}ZGS6$df340Eq(hf{!H6`&X$G%MxG{qll&ONV}y*%ltqQN21pdtDjbZ+m-(LdN@U z`MR5`Cu$3KhI^#!{>!0WQ8U(<{}HN3T-CHan18*y;O%XzZ(pL%ge9dI2^2p^U&f2m z#P$;c>9D`v$jPI8;V^3FX}dU@bx;~?BI@jR>yvvabnk3trxAxc=+mS*Li05BEtMI`q(AMWPM}cO&SzlER$Q$o6&lx(H6SQHR#*#P-!Rg|7g{lG1`HWh zar(nW4dykm*0lzWV#hhb`r|CE(3vK&3-ZZXhYl=TCw;-%8`GPs#mJVI8SR@gc+6H8 z$YVwpc26@5neB#?VU6z|ol(!c9WYwQc@o1J>pruEgU>PF9IY$N4BvN@CVq)QTli}E zx9alxD3&&uRieL@*8H$+-VYQ+)aLKW=*Tx;>e9K)8-7p*8*;%}>Co$sO6 zA)U$05I**)tuUp?v#q!|--XpRPbV*l^{tZFF1RMBfkxWsX#9A?Rj)@yQnS#V2Zft} z;_Cduk^jI?r?QNqJmr5a+rp?MZFzg^5+?^6iaTD*1lWYIJwI#1Eb^*L)_={7HwcLS zwy+lurRNo-`Fi#d>{h*Q(+;q5&rh+KzR5RpiIXwc9)fWkooO5>83SAFqS%KlIE)$& zY4q^wZ<>kJ`x!D){S=lEE{+<`dv>8)n!81rLIi#S zp_8_oIV4IDj(I#V!tpb@5ok3*pAaQN84bFehnqzMaETEJq6!k?o1KnPovdp5YUwEL zt?rj=L$tL3yEAgVvwd(2lk|5>-^hpAImv^%x599wEex3LyPXtr!ZvN?LXckfSmIJ4 z3Blot?!do7rIr6&K}&>W*DV5{k@T_F7}m`{{a?+mR{R3KH9CHKZ4*ymHXA-NI~f}m zdO@2{NTx9g3(fnojtkI5q^IL?UBYi7mE?m9NS6}$mIw&oe;t}nn2#X2VT%M@MXGRa z^3JtKvxl7RVT{x^cyDJW}Iuct`Y3x_}7o{wrP^h`Ei^YvaDD1F7R zY4!LO=*`Ft?n1c|ZXrn<&fdLIzFYojx^_cP-@{%8g}=x_;yE06?h;|_ zgoFcS2g*GTQBJ>u#t~aPh!qSVA^+<8k_{Zhh$*v-o)6b#3W=Iov8~P5Hdz2tc z>GA2i&QN&3wy%e#V%?S^D^QN>JCwB@?#lvl-S0v7>Cz-67UiXRi^Eh2!aIfVv?2Sw zGzkP&2H_>qF!(e9h0CAJ5pE<65+OtqMt2a%aX6yOPwu0@2q3bs z-oGEXPTF+`u)P^%a35s1acVskyQ_Qc+;M0gPg`2rBG?+}z|F+}BRE}*Z$er7YA@r@ zt=t9U)SZiyibHzN0YvOT8%VS%6uMrEXMTVIlbqlw=<~4<^ti<`%T7lY{P)TQ?4ltqfEuauRWGsreHh$_WB``#}7G9Q2^~LBj^lp z$$C{3Oz}kBJTsgG_f57#9d!zb0jr*wf?tHK43c%xS`Wu>_D3=@G zfG$kFJuYhrVZ^TrUVQ^|=2jHuFF5dcSSM}pq*<^tf*kXS#|mg7uvF zzCG0CIsD-8+lPwF6Ine1fUcq}tyiOubHBMH(A4}kMtu6TeKe+bbob6fdTm<*)ApA| z?e+)kK<-0QEWvv}J=)h)9q4-zS?|ub^y0AtcRcvEZ2ee%;pXa#fZo}2_>A}BYJD{h z#e1G9)jm7f9r@>5>SkDq3Cuun_SOpprS=<2!Su_;)OHjIL;mKc;8nDBua5_t05 zh_g>W4ThzvE!`5Fy;7WEbzBvDS?lpTLDX^6-Mr|gB9gee5O|J>YX(mx)62N#zQ2>v5%P=!U&g=6UCPD&G%OT$Lv z@ADIRhbUMbCd0La>q%_C&@8ccmZ0f|J(FC)902>sE5R6aZa5LJv;{qi-`4q^%U`z* z+QbPi{h%1lDSHm#TD)NJ4Tzja!NAy%8xb+>Bv3GLfp-L>iD6(2t&0bTK7#0{`6<_s zr9j>-1hawFHbTStv*J-IOY-|JVI_!?)A}u#7?%K}*^8<&6B^+U-v0R~@6~XkqPfbM z=^?dvPsljuG!;A6t~Jzi9q<82`UuYzG(Dw_h=CscaS7QF-%O20IU>N{H7vnWm>GZ> z3A|q{#E0Lj56*gazbmEcG8VFY*M$0|DUAHh$LjwvieP_c#z zmMOUQs+1I^tJ}bp6&DxB6|4!}Dx^gL`#`x{*%_mqz=exdRnPUDdU}20@4Igq`F6UZ zxw8M;y>;=pPa>f_<9qR|uipfw(FHrWOHWtP*8~Ivcm{Zi9B?XM(hTmuCDSQL6{hUD zeR<-TcXz)i`(}_=?0RtnX2=?^8k8NjGTrIL0UvlG<0GJ@$)-< z#20JPdVEdBBGrcsd(c0+`}HtlV+{UH=VKpYaWdEh1vARPNOfBKGRl z|9sW&%UAVZrVol^_gRfBauXazf~$tEWFXf_Q{ZSn%v@axeqH|~`0rFu5!Px@4)P+? zyI{%HlRLpVqDx`Tfh{ap?(rtTlpPCf^@khHU_yc=2zP9xRD5p~y}A?-Xb6!c@>~$M z7lo@oCI0%VA$X)a%5@Y>Bj^%nE|o`njgN7Dw#Znonh*0E8C$PzobR*{*c9=`@(FmHa*ZnpINhAOGrRl} zNL|P|q}A!1KyB+Fz}tfVE<2-79Za(*M_ODDv7qwSy7nb|z@<>Ys0td+`K;S# zAcbrc!0&~wpNiFZeN_$|Uo#{V_n9!nQj=lh^N5w&Y31`0ygdrh{P)2@19#x${dI|N zJSWSw1D2tzD--yUm18XlEtk<5)8p02b-%0X0q+<#H45QH$fC1v0tTa+{UlIUFL1ov z^uRz0e$U=u`h@$WeEkSIi7rs0Advm0#3MY!r(VfH;}nSX4Ji_3qRTM3NhzoWqP(!T z_xtmZh2v#4VBXyAP%Wflk39j8hzuY6RMbMnz(hL2rLwsO>ph01T)SZcX9_qsw=*|mWxGv#K^!aXUW!V4#!Ri`WtG3|2loiX;BV##K-cpns$MuiOhjGE&=Y3V^LJGcKB)TBwgG5YC z&di4*-25+eBE}I#utIH4T@@^~1mWhrrC|3*uC9wjI7BQa1uq@k2SuiG$sn7?4bQ=t zZE;H?zQ#biej`{e*cc03<|q;yx{KC;Tj=M9FS)B(WSh6~;8#iW2mx2nk*iA(o(VWx zObn)uMvhg`UMB&_NR)HP4^$)(DngTRjsdP8%uu4lBA|kQ)VTinlMI-hEm~g*2@?3D zS>pe@w_hSsW7|bY2$sX_yVawo=V53l0H8~QL9C?C`RhK*YGQgsXr40r@0=GA1GEP< zdQQO&iC=6U*!Y5h`+efmSBr^}F-TK>*U_4$uotEefvBcfO?6W$%g`)wq1Y$pb z3?7~JrIZVJ_EyxGBlGBQc9eb1*Og4AO!BDRT(!EFwS!fFw)Kfm)Ik><-WoXDwZP=urbdg3;U@ z3twu{w`OpF_Q-`Cl>)Kh=L#Pbo}QgGA_b3xiLk4k^U^;3RNwU0>6@&H^HH?_lS3tp z+v67%*Ap=aS@#iOcs``5SrPGprE(hfbXIaDnFWVyK^Y^;J*ZQFtgHrY@hY2v=Nipk zCU8lQEz|VyQ=ghtjfi3axXPsb8gQD+KRO_i-O&LJ0}kS zJ0fK?58B`u!V#Tv$Wlhi@jOul9frG77Eh9p^x(G;6;&wAYRVM&>^P580!M&74fvqi zo=Ge<2uP~i6+Qy98-1c}}FW3@r|_EV#d}SE)I2&$qfP>xo%8N{^`!#Uw}5%WCDh*aL{1!&V!$) z5$=oHQY|?Tl1%Mi?e0&v1tEF zOd0a|{BT+;m+Rlc^>2mq=T0^+q^BQGU?OTy(SATT$!GD}oKcvc*M&vj#7dLMg>Q31 z)U7=+!|$}O6QJS2W5V`D_|(SqSWN@R@S$n?0czS^Rcdx?!KSojz60ssN!H%E5QnL zkbW6~@P~JoD88Nwwg08r572IWl7{Gg?Wg<+5;p1nBEm>j}ekB@2g}2OJOk8R?`PgjDR)wKLC+gSD^jOau9!1Hs%)3-qX?uA_9MSpghnRE~62& zi%muP*~@>c)oAWx8pkidoya05J|$YhQEhEN63k@jVvZjHM=&5~W&*DoiIe%<7#n1$ zMpn~OrV-mB^YU1Yr-oh37b>O$Is$B63WY(IA}CzCqHQeSVS%3q)HOt63icU%RxTL+ zP`sK1iLmwg!7Avf40spp`&+QK*RVJH2!%yqi$%efPJ97S91y}i7XZ1AaGgi8JLbuO z^Js$}GWRf*R{%6OJ$VkJ;*gZxC^Utbtmk?nE!`s@pO3}Q9j3u&aJL~O)KQR`lD1K% zS3mN^E`=5ixF!FxrE#0z6xzSE#dIO7(M5nNDNMH%t~qCakEu!Tb<(yZ8n?#~-bxgnUTbm}|LZ0lQ60(g3$Ricac0S*!RBz>XY!-;Y7W`! zdNmvQ1HYl4Uk`pYE(!dH;Zc^Y3N0hxdKjGeo+P z%QPLX+;}LpM*aAd?Xt|oXF@mRgs*^Rr{%#+dWUvMPva7cIACTQd=`WDp8%X_Fdv)% z=c&08uC=9wl6J)xlOuB+ijMRZ!==^;CR^K6V3QkHe&iEA4Ub*u;m^0<3nECCkZwP4 zaqNg@(DEG)b{gs>g|9~nPpY4EDztJ4uCNLQlX@y;h96SI5685h7Gc@jZzDH>=7zHrzhHslUDXTKWBpmAB5h z1uV;%R!>d77(#yH92Z=EbK4%i!QWPPO{+!*G9aZ-b}~;%xbx?jP+`25-Sw~6?dnOk zLw@2B+dowiOk8|Wo&xolx=e>|{gc=z+>_O3TP~`=7#x}$FdM=I>@_}hcw+K4E71OV zs{%4B>Bwg|R1KjsADPyGtLb8XkoLUjss#C~;9krt;L7r)$CDF|Had`2<=(Wo1BZ@N z_Mz|0n(te0x_{JSFnOPaho9J)1nY-IgKTwcA5c>SzmRBZ)@`QNOv^NlOYIliJ5F`W zG4d|j*s6Ct-67#;)-g_wm-G2m_a5ypUZxpyJWJDjGY)!wh{IX%OPK+5r_e0q^o%f#iO77fEdUddZc-+z4j!*f->s<~*@||)fCp60S zI9+CTUmPyi>Uq_4MK)Mv-3Y=%jS0|aNPX#U8*{1^I}f)_$m8dWUPWPq_)7>+Nq4Z7 zYhjiw&x+Mz#m2P9#tM}pQ%_bE&x7x2p+dNV*RK_$gI*$cJ)Qu!W+bDqC88Z0^t{6C zHFbj=HXS{2_eJK>!rDIxTRhB#t?b_X2*0*n&0*D;cdEiw&pqurZ>i@T(7-<@nGb5xRRY>*@?Ed8&2g*S33WF6SBG@DpphD z!`i!I{v8K(x9gqmsklaR&0g)@w$ow$Xsz4t=5+Ny55Q36iF7YLnT<8vZQl5)$047ras$m>kb#W}lIL*DbBr8s?tfbKP zcy9SVDQjfVXu0l&$qMYr!_4HL#m12PKOqaQEWYnc;1tG3*sqpz@D*XO=+ z!i9(aTsT^`@_a#8x>CUd{kskcPfGPJm!HQEde^V_Z=P}TtuSA9tVE$%Te$q`!Bt&b z`mQCLh-k=0l0Lhp2!oOlvCQF+|Bt0FfrmQ(|BsT86f+cUifGJC*;+@c-6=<97?5IM0AWKa@5c|$1#j?c4%5xL(wGUswKu%x(u}qjnD7@`uP6$@vwOeWBXuqN`k0}}Q*JZnO#a^jLx?_(ISTGpt+=6>)< zpU>wvags&SW^CeGlt0qGN#&cTPr=P>W%oRX2=CD0v56De-V4XFUbQEZQ<;xISoe7h zlRK2s-2N&g*nhWY@Q&u&h1Jy+WmS7%(k z1;iU`HA#d93~bKpp7iDA<%e*(M*lG^Ji;T-76dmlTAxQCqi>f>(zRyG-65Z)53WRl z)y1yZ!~FRsASoBJDtW#8&E*=phLf+2&n%V&P$wVYtqEnD&kzTFOvVlfp*-GPp+Z4* z;5nD)n?X`8G!*)aBg!4jPN{vjb-MK9(30on-<-#yCfg+=9&5=``o`o zP5#z63V8|_>Bl9e0XLHTk2-ph{1$KF>Kv9-dahrWk|aK~I;}IMF}QEi-ZLgfbZ8AO zcTXEcegC#tERIgz0xZCDDvrfJ>S@7=Il?|0F2Nic>_7Atjzk(aj{C56lS-JcT zZuaB({cYSuxq!8XKVcp(__YePK+{|9+_65(mR_>ylu?B>r;@Jz*;Dx20l_9QBJB(A z262fm0!Im^u7G;rkmnGC**QQ~!ov}a>&s$jrp7j!q?oX{Esp|Tq?b`fcG6R-(|=Yu z>;Ml2QKwba_m*|1gT+uf{OEw{<=`8FUzR6_;ieCo>+Wf(`%oNZ@J?}ZZ?NVrzbHPf zV_3OI+q*0e@)Aq}(zm01I%g#LQu>zy?oacY>y6N2=KEa}*h)2fK7C>isfSmzEc4(6 zRSoe-x|O?{+kzgmixm=$t6W+^XiZkhgRA{XcDBpyxBIKAWk)gAl`YB!e`Zpg03<*Z zdn~r|RIKWX_FGP$B&7zEg^J*#ijd-9X1b3MYvdXH^258kc@9x*hVOMySCH~;9vy$P zx*(m@`zjS*(D6_8_hPaY#0<3NIU_3(hvuH%c;u+?r)nm|ibJmQPq(_3q$IWaj}^V$ zfPPh&3bq#h^3MN1U;iB`+rR$vPW}(EwB!@`w?=Gabo=%^iHGFfS^qy%|9JoBs|#5_ zA{@Q;tjPX-zCE@5Wl-mrZ@(kYrdeblZ8Mf}R}&qkgTTf-JMcmC(fCq<0c6Vh)ySet zK`$1R8lRjt*W-kqT;)kFhR5f?%pvp-a(ixa;J@zaU5l#(xO~3R17mO!u5AJUPzxZw z22Kybk+FBD$jVbG3T>~_PGE3AU=(m)IS>MeM!cpg=gp@$E$|)5c&%A=dO+y2utN?M z1=z-K*UD{2C0EZZcwKnbbGu+2MA1m^k9Yn*dY(aPK0CBJ)5=%gOBts?fMNlW(|KO2 zN-)`z@&Pw!T_X^mh`$Lr4rF$%XG8M`kvV>_OUuHeN=spRg)Rt1>bN+&`&)RdcM8Kv z!|C=)o-z<+<#Q_*t4bg@lgepB8A^LSuIph;i$mE znZwl7P|Zd2#^XKVe9=GpmHf;fDf^Im<2c#YA4XRLcVBR8 zCwtJ0-g58R$A`OM%rqV8U^1Bu_&l|P<_xou@w370 zMi8Z|I!e?)Hb<<{#blKwrOeyraclF;jZf$rcb%tlq0t>8OUjpyW`)WjDAI9E*W<^A z{=;{ohdXaF!!6WzsXy5ucouSbX9*MI4rm*hg*v#(M<)s(ECn4jMwhxdD~~RDGv@Jm z-j%nrbNlYiSQN%mKpdG3Ryq7aa0crTyLEoh`9kc5Q4t;ikglLeT@?;mKXqK?DxCRY zi<7R3=(v6fL)xa$FHa^>r|mT0@2_7Ib#}q2E@2I&M(}m#-K+!WV7qcek;O6Yd!`P4 zvEbFn+odUswi1;X;xtq*2&9T*m8{$lWE+Y|M1@ELyJ-9(Au?P4Ho=1g*0N#0P*GND znv?A=Eme>8d+=C2bF#PGceWPQg#a7#Uv&IIKOG;za9?P3ysi?<;8TVG*<8 zj(-B`CuPp)n)zyw%;n%h#2BO3At9QGNt!|@AU-{9laGLa!011ar>vaJDf88y@BJVX zH>*z0R9W7A#X4>70u?5%IT^~j78!-92euj?v}c2}I9f!1ccSQ1@b9dt{?uV~HzHTQ z{5XZ$bB<3LK{~4n$<{4dZ;jIzYWJS(2|=5fPLywjIR%P!e$crM!>_H75597h zbj$hGMLLIe9mayGx<3$9=c+>2jcj0b6sYHc`d=iLRa{#i0!h!Zct zJV$I8(JE(M`-gEVe$Ue4WZs9{6fbwWU84-|sw#lZ8D`;-cBq{s(~=FRYm&{VLAnQ{ zW5=S3x{{EgL$SAPkvjU1BP8{T*V(LKhTte_5{fiqIUYF|GE@KyEmgrJ0M$BR(g}gZ z&%PO;??g!n|8@k-(WLWZPSk*iXyE*jL8MMs3$6qg{K3dY!57#GvIlf%Q1kNgLY|hC z2wTzE79JS~Z*Y5eCc2V8YpzxfS=!_$dRK>0`<@G}=rbR`c*=XE2^q8J=O3sS|2Ap9 zvc{uJNvSgOQ{I2>l)=?Oc93K=@DpVQA$vLt;co6#q#Q`-2di z6~R+&!{!QJ>%mR~uKjiB@Rx+ZY@3N{_*iMetl_tSdhs1>$<2(8uiOf{$B*~(0OVDk z0!x9?N?(cuTC?$Dkf>ZxBP9yD);aSmOf=cQ@f~E~z%$2^h*(zX|M%ZQcP!*AuHa0Y zI^iktvIcktX#(hMiY(#}%1C?DG<>kG!(G;C%;}zfQLet8p8JdEA0cllHMq-I^^CCX z4atxYy#s|19hZHe7rU=nk(%z(RZDlW_wZnBd|KU%?;c>1@xj#s4wmhSf+SI@Ak z_=8B1W(aD4bM_WRxIGxU!)Hf_xFHR$SeD}hXsI>)Mw`;j9w$5WdQdDU{K6w|M4<$U z1I!_a(<^)}mhgXBVc?(|)6(W6{+{pyPC*eJu zg|^Nfl;h*-cmQ1*8nm^m1v&l zCOG3rMwwRX)o~heE$QMjyPEg`&+6U3$j*2N6CLm}TD5@td3VJb*4Br`N}gK_^BlCZ zy{m&^mIK)w#83!dp}HF&_Tck@ysnU1MusJW$V~Q@&wi|8!zn7ASthWgz!bux@T?TH z0FfHXxUfbyVdgphuxS0fP>!AyEv>vNwrp0wBpg{pN9GhcCs?y~d&}KV4qmsGd3Rni zCNY|xGK{2EFq0xVi3F!0Qa&mtT5}yEosH>iU3w6M3+cF>Bp6>aaoNhLE6UfeOvWU3 zfgLLjcmy^@?kHA`OTc%gtRe59N8~ImJeB7_E5{20M+3pnK8jK%g>z)*Rl+$20}Ndz z`UeRVW*VnmrqqHoz0BQ9q<|&r;G2PN><5E-38E#;fO}BBh3JOK-46;>8eB?q=C^6d zG#_cKyofYw)aM2xl2>dC%7@fD*-Mdn_rAmSohMqHV;1Va3{JM&;j!`7<1OscX$9$OmwTO4E{fA>!e) z>YE-FSsjr%6X}KGJrd^nazk`|+q@pD+h{2Bg2fDg*Y~Ro(V&0XpV}c!5eEyYnA7h0 zya<}93~HBOg^%*a5xnt`~6llgxG=sop>Nb_4pP#!2AFjbFKSCkpolHq*NtI+E_ z=(}1DxExz^IsVuFZ2x5M?6P=CV3|-oa_4=zYMh%>t(;ByFb-u(@f=~C_A8_OSHof9 zdw+Uqs`mnt++Xxs&iBGn>ztneU~Qllb+21BjT$iB){BqKHL;+-NsHI-jk7pZIXaG- z_&cowhOdBmAx5c;cJCh45He%uG^NOlLs~!%5qVxa0^5IiqCRhb{BsP1U^|}SB)q>7 z4>+_7zSd&H8nCGYP4MsJ5+G0%?odHu7yLH-+EBvJmp9B+yGH5ThQG9gZo5%&pb9YX zGU`0OD=wQ_dTB>r)G0f?z`-2ot4meIYfsx^sr0w#vQF@u_2M@0k(c_Xn9p9PG+j{SDKIVnJ0bRXt2W%9JCYl55DWiiBDBvRX8dqPRSN zY^QFAK%l~1(JJQWlj66b8_kJGBkI7>?#6Iz5@&j)H`^9Nd1p)=SJFW*VK{ZB{1h!y zMx=fZ2m@mBsA*xd3`~JjmHZ4rl)RZ!<|_XG1SeJ;&)Q|5r^Vqcr=<(1V-F>UUqPWp{Fnpzaj$pa@$Yf#zNJ7fO$zr zaJJ=sJjx)_06-dtC(?@`963u-z|W%K{K>G7=XE1m&BKFwKV|YZ3#pSl?Q9RT;%gOl zpyW3|&+wl?PSQ+K$x6A<__$O5)<+dF*F|B#{L7km^6em3@5nzK@ei4~JIetqiW@a!gGA*?_J##|QhL+C_h!*ED@W6t=A+BYBi)t{zDYQ`l6di~|bi z+T!5ThYV-h0cEf|MhR?Af_Xc)n8&bj_;9|hJzO2nm2crkHz_0etG!$TJ&SB(IcYUH z=cgTPD%^v!JROU)6lZy^au&L0jsukpKn4l~?MS=tOh0xp&=72A`MD9@>cQ#ZJcs(i zwMcjTBfY<;!afbC^7Sd_GuYv+q^;Jmu5$LLXMEAb^MK^NXZ-LFBg!@lHgn=0uVVYo zP-FuSNRsu@mmH4t;5#l;4O}K}|I+ES=t7oe1eco9Y;D)S_X$(vQB$J6;jE76jSRdb z$@}c&AdfAB0YALB(wO@V-p%O`(uH_sr~3WR?a#S!@9u9z-{`Y(<)hsWkQM~GX;5`--$npZf`yKcFT7xhyuGwSG`j~#yhqYN^|#w zx}~o;LOnVvunO_cs^Aq|-UX9Kj!{$0d}kz1hN$*^%6m{D7%|tZa6m>pP!)9mmaWa+ z9ufE|O)T}H<&0e5sR{Xy*u*WLx3p{)+#Bnzri|m&!=;xr?CBEb-3qm?yOCmTYz7OQNy48C;F}zfa2#F&S-{UF|#T> zy~CDoFwyevY0%D6brz|Du*w}XZ$`24U;~!8YVPg$w|ydmB0Hna%GSNuyIk~(LsH(^ zBo6IHFPD>&5`v$<6Gc8iOh-}pgHMd*9oPh7XtNhEtx8=`5pU zO?9Lp7H$VTTqvW@Yai1tvX;s#9ER*n+v1mvIeMk(BJU-C7VoQGN~1*t2l-5BC!03b z*qGC=mze-asglZacdOqOk;Gft6gI`lriCFAqcF|L?{;Dz+Fwp$7n1kuH!Av~6o67> zFg&s=b^+0!D)yZC(BnMPevw7hh!jM;lbeJYRI)=qRC4Z^-l;e_mc_jEj|C{0O>YYc z4syXxe;uH~9A$iuVgt5feu*0qemY2uYY~|PoES%iUiNG17v@}5oXir@O(yAum|--z zE`6A2j+Sh>*S^+o8 zbJ%B6hAtF&)2ckPt4U=9)wqwA^lJM4I}m^Y&bQx1Fo#y(f1Cj!%U2{Ivp%Bh+>Z#i za~fZYluBZLV9&-`L5eAlwOFtH@@JUElEFNqz)p>W)HA+6c~TFKwX+7Sb*6LIW~->> z;nO9yc}J~DN+Mi{Q?;mee4~CBln>(9gccMxOpzL%F=@P@)i0f1bUB?aVh8iMvb~Qz zyILN^k6wUd@*=Ybhg|fkg9JsH3`7Iu9*%lOk*iqHM2a zS19F2D{6yX?dswThLO(L#FI}y9L&a123Z`#sTGBmn;-Av{Qf#Mo8WZvN~f90Iu}5F zZJra{Xp|B?i~JzY>BJIfJhSGxK!5eUIb3OSH~*vGN69r~vya(o=YS~I&ezO|pGB_n zOjKJ0b3aGqqPPF)N3YT=Zl%jaY#q0>G~Feu_7&&6*aW3&DsJ)G$#T9OKC8o&zm(Q& zaVK=&v@MzM!Jm3jI~B&gp~4K=T__3cE#4D6y5X_f?whMh4-oDUOc<+z%{K=2WX|Mg zyf+(5&izs~m}@}yS=zI@hdbGqu+Zm3Y0yCom&nA(T)t76(E6&vP=1n)3mw?l=~O#o zlb^N~?6Yzj3j&u0L~Q3OHwA}UYxZ@AjH0-qkGy=}Y7%Wu)b36Ai8B%_ix-Z?00cR0 zW_6j0&2`u3{E|nvw55h~%U&6%wAwg>r%20(pcDYhQVP*e<|L#sRWNPT0pP;96*<#? zacEdZFp_x@b3)=n-VE_S@1;sBLO0N1)6gu^$Q@v9JTKx_?V%TT3^v_}(x`L4{!m{z zf@8ZcuLNBCo5_yINMlQpNyA9T{-whb+ih%hFBcz^q*QWyx-#81U*he~sS>YeyrG$& zE{Afj5FQzx?Eevm$lDiee_0O+EW|E-?z+HuZpbYbhxGk<*5^z0TdDKoi47;+&y?h9-^ znc<;69mxr@E!0RIRZ<0>wQd4BBTDl2u$ef z`&^JuVR}ZztNa^xc2K25IghHwQ9$yWj6|Rm@s&5x_PKOOd@A#28>)_h6J`9YEdYt3 z99)1pKyY=~gxdxNk{f4zFC(8j(x-g~T*NrrDkHJF3K%>$>#KqOlrMLVM>X!tHQ8&T zz56=#zBx!@5hx$zY|8x#6v&`wQK}i_(QvT%Fd$%%c7ti_a4YS$OGs~AGkO5-N}b?o zFbvq;Wi5%U^5i??SNeH3m_~)>iaZVW8h+z_s-X<}62^rRFnmXOp_U-guSc#^Q4-Hq_)+fil&diZnNGQy@dd zD<`NUmj)Ry!& zLHR>uX-HR`;iOl4$4#lpi|SZE&KuMEB`>_qBXy zDbl$azk<~@$_zV~iV4!QY&&$T`Sz#fqKXomePN0dgw=c#s{7(@RYj;r95JB2D%`SZ zYQPuWr+1m{9SrNrmJxR9pW4kn7ybxAwX4JCBH(P;2w4!OH6hrR>NqQZDjPR80^lDB z{&D=@ixay$3+7hRsChr!xj)@EDyv)$hMGp$eO7KCn!qHvgueBQ1xXSh;6f?Ps=?{F z1pXPV$+O%JJ!MX<@;K}kX|k3VCDcosdwSm(eW^Ry2eP_;=Bw4T;3_9|%cKySzyI>9 zvZ!<fD1S zdisgLT}z=TexW5*TrWzCjYP&M(!a2TRsHI2p0&euME*DN4VHETqr_aD=}~lF|PVNF>S7Xc8pKrwMJ}`fX6PUE_$`U zYb-5u?#qMNF~EHE#~yS|Q0i051vjc4^y^f|KAl>sZXA`lad~xJ@(!N9K>%S8V@h zA`ZXa-<@SUpqJ>Pp6+2*;-<1_H06jBTlt~rK^k08C^;q%3Kcv4J?F=~eQ2zT4U2+7 zLMAhM;$Geas0KoDDC35xYSJVSUK;V(nb4I+U$q-~88+vAYL8-3`Oa|f)J>JBx(9)< zd@Aj{^YR}#?v5%4Unk6@jU_Lb01xiU>#JZTUkiXnQe*^?`^v#!xwRSq$+ik?icJSS z`*XA`jqcx7t6;^w5UGCn_5fR(_I(^(uD^(^g>}3vCP=>SBMveW z?QdH< zwkDs~2SXjyiafgZ!45O0=dRc->{C%|EY0m|m_|d;%@V@fF4De@cS*`+C9l@093>jG z!uFt>VMf&jdba~^JGjnjVdGnyUxtXsBmTb}&8)K&T1UZK>1lxYt0Q&N7Y97yyKAj> z=y8W2s5{_qR(sm}EG7AZSzy`qW!iNj)0}(V$}f(sd-EM}NMKf8;!)drfqBozHlf)PNQgXK! zSD8Y>sPGbL?D;0$^1d%I?OtioVor+L{Zq-8k4NnjL=ikna!vns z%B{l2gUiPzNga~a`Bmd)F_7$0RnL!7D{&qXrQ3j$Xk$)A8V__}@_q%rAgL*f9Dp4c z_o2{H)pAUfb{VMH8u`H`jL{fD7;*y7;g63WQG4+qIrw!iH+{Fo9b)^ZOY)lHm1_cj zUH5m$3w=9_^MzIW7e9T~F*1`2x1pkePo9`m>4R4QDFG1M`=I%t>fqaBC4x#DO&U0- ztV8lV!xlg9cH*sy9M~|YNA66o6B%MXQq3$$<|<8lrkzo_cR%G!#XL zm}bblZQ0&&dw!N30DPJXiNrq>6<}plUkN@678Yy?_8rA6M~~C zXR1WslVA5oa7#DTb!GicOtai2ic7!b@HRBjcK_zw1ej?G&NmG!oJxd|;E2NiER6G} zA}?!)z$4W)oDF4bSuU?3YSi-}{?$Q+3jB(QFptAPMO||e5var)`_2ySfT0L4ybR@$ z!nu>18X?3ghzb@Hc zU{utppGs={i+M*nDII%BVpa>SQ{&rXBjXGvVk1PPj=W87{W9itTxbF3&fB`m*wy*k zdBKB1OTVN7%aiX#ncxXXhT-WU@0S6bhAk=-g`)%n{HhiR)(kI<1ZWQAyCnLNiB5`2 zbU_@S#%qZ2$Z+CW*O_W!mf+TpBOyjp{dJ>->u6r-%f-9tCbw=iYpVUN8yc8gah~#t zO>PGPvLqti&ERx`R1Jq73u=R9qO(k1Mrux8V&-H+Ia~YE3}rk8I6@cvA~gTyhEQ>% zU~bf&^*h{-A7BDF;b;1G!6bzpi2QeQEN^wGgBo@HW5)ZrL#Q^pr0vCFnU5 zXLVgAMauQyas^~PO>RNB181!3PD@d9OW`$6qHQp3*OBeXT{)b`RLBob^(-Ubj>vL( z!oh>zIL~b4^9t*Y5DTLBEYE z+w8UL_oD`>au0=D>WS=eA5(sO&=}fF1r?1KZpIE{BC9=uCMqg=Z&nuP_{7C^z(W~Qd8gR1A0;5 z;aTKrIG3#Kj_xv?kwjVuL4L+jS2-{d(vmv9KU>Bg!JzjD(FYKS?9~v|$W9IT%4r`? zkdr+!++ECkf;v9W<}%3Xg$o#oTpD2Hfql)l7T8Cbq~@fqx4*-?1?o zY?$oBn3dwpc4`4wiAz0)-ahUAh7LTf|FDaB_9mNzU-Xo5Y0qQvy6-!eM{h5#KI78E zWfLD36H*@py)gT%-%h|MQ|ujR}t zA7`K3)G+@+p_QmBmR}Z~p~oAwGe6c_!t<%}m`DvXzzn8Zn*vOdDsaB#h6m^jKzto& zXB+aNo(i4D!rv)F0fFKuUSCK{xC=7c(hw9Zw21U5H0{6@MG}rJ4_TDz)OBlh`|W*? z3oMw6EWVT!E+dRxZydX^_O_(sMM?p-yP}*{U1SGDgPZw;S(-SAO3Ub5;h0#h6M?e{ z-bDD+Q5J7no1EdwccW>p^cy{$-ZGtQCbk$xPgbmmpeSyh8P$u!gbRvCrNbz^(*~f{ zaxK=Oi9Dkey9nzq(Q2+t`?cFbZ&lu7PpmID^Ob+gjpLWyFBZ3H`AFjEm&ShDQKu8NiXql%M{2&olk zr-Or&IO2uA(=o)qr>-jhQ?&l-ox(=uk&eS1MN?f4jgqy5^>ruv7Ts)BzOvcI?8Jte zn9++w<+bZ0qbpJt`0FwOuM=ABqJ9*wLgNgBOcrvzksKkkQ;s%gdB#z z08qD~3N9g}bqs0wpFOO9&LoE)NWW7`w)3qU{c%v$^q=6bD%X=<>tBkeX2kE54jI3HP0oJl0)#~AW5>y67VnUlo3Wzkw_5Y9AEdTS!% z*A0Eloj3I!!}V)Dyg#DIul-Rgr@f?Qc%}3wewk7#G3G>zo{r3BJ@(r2S77cyPwFMY zr9!*)x-TEzDBgK?;Z^=HUV7ib?)2wh;cp&OPXJj}Dd^%UQLUcJXe5p9Fv|JLFpm4> zoiab-(OAmj{@?7sd#$E9a)?*5vu_`c$jU&T6)c$c^M2{QTstzCeu8WyId!9`;c806 zu7L1>$h?aKlYa%RKO!$Q9{I51f;var0I%!zJA(n)QPEk-Wb`kZ->K8y-P0G{Yhmfm zLUdj}?|9f#FL(R(K}Ds=XtU*if{P{1)<@B+3M26rNgVD86OKF-bIb+| znJ=ot34yJ96vcRw3{d>~5Lk)6-17%G3!O9<(=Algh~QG!4iVCT|Lc3x%#~? zt=U1!*(s@`r`1?=;T_>d zVdx)(ZPzEB6&9WGC{J6|a=0UF?HkyJfk++5SI!)gMdrz^cFZJL{;EF?`=zg35P2N> zwP>5A!^(2Nr|u~hR)A!nxj0VT5rwOB{=sy$d`Fqy>_3rTJF>KBjql`7)*D5!bCCdw z5uuna7Hd{)XwNk*LKG$wcMH`4;Q%#bL_)AZ*Mua990ot^qy850B&d0={^T*QvtQ4I z(y8lm)k&OMOP5bqj^Dcc&-;R-TvaMnO?@qC9o^g!qYV1m^21|0zsrDOm>VLz}V>s*WW+T=VgSZF7=f=dQL8|EEjetN$!OWJT24 zF#y`t9-L07LW4xYLUafFeg6j$cbbZ0@;dgfSUj5H##OaU8nU*@OWf)2Zy6h>>)|JM z(zVJJpO4)=$>mpf#pPGyTddfD`Gp1xUsw#LN$hu@Zf^n9d%NEBnN?kOWRN&GMHipF zx5DCF0(sF6q+X{n;u>G&sb5@tqMQ9Y;0 zjJV)%7x%&M$)?`Jnz$GL5mJ(#uiYcDxOG;uabnLs{&hoT*?t`wj|=Q*hfD}l(}ZS| zO<@5-3roheaW_Q-UGpUT^Y95IV#%UQcxwSwMoiU)7fVKfpmp}MB!}?xi z?!mw%gy_B{Wq*BC{`7ghWUbGpIEG(ukvA;<=7p1Me&=I zTOXm`_m$+jN#2~<2JtoMB)eVHSOcQ-ykCXO(vq7I&ljEj3iWgpDHcLqB__xNK?9#I z@+^WrxojZFMzd0lcbH==YG-3*H{f>M^u_k`y!JpN^sLMzfyit9#g=L~CqkEc8o!+f z_pl$JFL+tdFM&%!&wHMFJm`wI?Y_@EroP}tHgnH!KWLvG+7Tq2WCoBLBX{PM6-n9q zv8^}ZHxWHa_uQpl`jn?c7L;2G0g^cQz7#Oq#mpO+v{&D&a<{D5a2k75jUL7LKVjRZ zT}Wo~0u%p8^(=574jm0D1jj+mFT{rrcjCY`xl$f9NkKleQv?5`Z!y1OLW6pWo0m*) z-}l^6g@3Q&X7D&yXvq#Prp=dv9Kw2{o-XtK1|Df{N_2t32@mf}YgU9nMrKA67U#NA zVLt>Y+bdzk!8snDj`H!=46;)V?!yy2!@&1*mo?J?X1kXpEQFR^FiW%BAcoxR~)1r_C9`{)srl@6cTd z$vzoW#eW274hGug&KJf*WW-4Up}2DLMV>ljly#uu8^kmU{GYhzP`licK>*45#I7Cj zEYqkzW3>k=b~wr49(g;Hnep7llZ%H;)_z_=igH(q*sydobk$n#Snbp8*%k~S=ieV( zLfRB~b6nLKZ@0pdJex;XLZgjx7u>2FE6D)xp00sNgXUaA|i55IlQ9g?tc`TBcT?`BNO1lRWA*y zL)2U}BSv`%9CxdCJM66l!hJKf#1;e*2y>M6=3VM<6&jSczE~!72BH^8>03w zdjL4V6r@A;5bkf~hO@mu4+^>#bK)n{_^tL>OTpFo(>FmGAcSixVvprFL%oDFe$0d0 z%~RLi!V7T$Q39x_+q^eFUfo~0Q_cOE>Y7ib;ue0p^%cjl`y@x)I3USKSoEVDWqWLW z(5Kv$&eQwizn|V0QKoaANbf;2zmLJjD2TyX_lBtKA`n=WApw;ZPrGUMJn~~}*29dt-~a#(bNTV7#rPSrIIe)&DNJ6tJfjtDH=fJWJ_ z&@&om_zhSMT*cOcE&}tj8On<@(IxOPgP=*j0yko9o@9Ri-%-t4K?$BG$SJa?#m?a# zmxn>N8)WX4XN^R7fm)zL1b}Ev5Vn%ANvvVx7R(7DI$c|MS+XFS@Iu_5{Uz|8^I@L5 z4BWyS#e77*CiK`oUaGemOSd7(&+=l|9r`xrRl4B@&O~|yRid~T zHGs0QW>nATHLRq2{Keefq~unP?ZX0#YmXMQ$j+;0*vu`}P)qBXSNK5#ceC)=+9FFf z`O?|XUO2w!-Lc>RPBh#;f9vpt{yN<6xTt_RS>xAxmyOM zw@_`HA_Y*H>P&xmMGurKLB|CT{HnLjoVr8YxIU!?+U>BL`8YgWVc2J$yHRedznN)< z+n1Z=Yo#KyJ$^&m0q zeP$-ZlAQ}hY4=94^XsLY(z{YS33;FpJ?HTm(fh_o|09I%mHaK--N&wL>Fzv}eOWN* z9or;gin;~luZoxh+Bs(YNV1l$w!dTGf5%I#H-*l1(^CipH_9guy$$Hb^z8xQD?}r6 z$`nPa7;X@nQ4=SK)PU7%w+I#Rk19#80;D9v(m}5$!JtFPIBMzO`MK% zR(5ih!1QmrMn6QoajB3rng!mPS--1^%SKf`-2-Q;#6+ihnJCHmRbO!?h# zSZoK5<73OaC$bjs2o=;W6I%5+3T@t?J9GM-=nkY=f2*jquD}A0slN_TYlw<~U=29K z#Z|pHoUf-?R-&}GYfb7dUCS8!Ez>NkChzLdZcT!nWZ2QYWB5w7x@7Z#NIpG>bB$*S zrp^#mspx_P2&iGZ_WZJ3W0=MOOw_{zYkN@b%Br<+mN`SHZr$nuuN%S`pmE^trC9DX z^kz|{tF!u|U*NG$0hqZ!pqKlIpiZ<|L9$IHY85wosTzCfSD*a;bF6&zwqOSXz{96@ z``2jnFAh|(%1L9V%l8$3N1d2bSZS$#r!mnBBf2cYoNJMjY6y) z*_po8`VP}5(f+>2POHx;5ycR=h)JWiW<1Tc*Kk)EoZCl(EoBq1B=aw$pEK(H%YDZE|(t zJk?mb2wad@jdzM5clTV}ZMs!JN{8jNXFpE7hikcX;*yf{`SM2xcceH*B27uzR1ee& zWJL}os=GlPA<^n$hP%dtOb)zg8gF3Z5@r@DywHrU*@TBfM_(gxWVxIz3Dv45$z+eP zy8(tWPK<}|v~5Gej5E`BMg>$rGrySH)w%8dai;e7*=Z(sZd z(j|gHD#MsFwIZ_igJhIxZjyPSLj*C}0DkOQMW-(7ev$Eh9NDb}Che%F5S=yfMj2fI z<_YV zKX~q-HEVvR(yPD_n|>n1dX~191D1v<5&+$rsh*QEK)p#FnXRQ~dwc43TK8+W$^rb`-Tpf~1Xnn-D)HR7{JUaJ&d$oXOA=7U~R` z`aQCCIMz*fttdTuFm5S{7*jnu_}YxXxmgSRivio)_YmrRBf2)?{IzC1IMYlan1K1C zeb>SI0l+4Xk|nXg6&;8!W=6yG5qWf&Gv!06?x}Zjkw>&pZkG}b$z;wd5iUB*#LH0} zsAJ#$H)-mL$+~M<(Nz0%_oh0_=4_M!gNQTRRhFaNE5rQuJK&4HyU1ui=%6CogSZI7LAudf-wTO|N zsX7IRfG)5@e}3=Mh{b`hPoyGqAa~R6W`XXtD7=&~pPIXlbhxs5Wz*tjq z54weVeP!4OS6WS8seYBqi`1ms95B6~5V_W@RTyLJze+aSU+UHZprJ3^FNRMwbLx*6 zxbPNTWNjS$wGY%{LwflEa#WV`({WJuT<~GoS4NuedS4QbxwA5WV7< zt&*Wg>~=$y%Yvo`7_qWDb2<*}#>f7;^6b1-23IMQyAN2cul^&@EaB$~J}(K7-f+?@ z-}|(u**m<8D4{sYT6Ek;YmNF)zA`SDCZ|1fN6}8jPL>f)-c1=?v*BP+L+Xa+Ca7H$c13;#X zjSw2i8@LWNW%uuZC<|H8`JBu%1TMZQ<1s>LC#=LK#&0Kq5GcG2P*y%j&uu{ zqIMKwVwvG=4+o$awA&Chg5SCY4=^P(*ZO%~*YpM~%Fd&F50!AMJRHivYk-?TI5PYe z<_$44hkA~V7&`G za|1|LtqwZ_G_Bv5g1>Y{d_+h;UKNzGrgrc@Jxvpch>oWxaXaQC(GKu#cVUQ&Ibc{9 z54wN{zMD$oFqWf`Sy6_4XARMC*np{nN(c70!KLx%#sIPdWtf*vnFMju4s?K{nn^Pu zdzoyGpk@M1E{ididbrx&R}M0+gHpcpz(PTb^%+qZsi_1Grr8yabif~^*FSRDA29&? zT@@P*DBlV=PJBb0BpM3VPanunhL480JriW^+f__P6dD-jG+_;HFi>G3M9GhfA{W64D zBhDsWDGJZm1#pc}j|DXPfP?S=MQ?flp5{dx{@)0Ez}>#^W+4#ww>Ee@0p>yin+?$= zLUii@EN?zu%rzz-<0M0b27@8@ABG=N6gn3KA>v1c(97^2W>eQISx68g8eO(o!gsC&LDb!B>z5>}u3^5-4{K zrozm*%s(1HXb*6oVEX(57wG`*OA_Q*zPB7YnM7=CgxFK$c{BJ#TV%zdqf!CkRVg2V z!!%$K2) zEIn}dPDQXG^`vhxmO1_S%{1^;efq5VQeI(8IGtIKk5XCIyhv{teWpw0v7<|^)8@%8_VdZ7WlveQlv=3cTDfM=2kPRM@QKHTZ^e4P{83k6$tF( zTJi=55c!a|vi^GnN|O~PVcTE+ZPwZ*i~I)}b~&z>qV<0ZyeM$116ni-hnK09K86Sp z3Yy@r4Zl5s1Hfrst)VEQA`B;`&5B8pIgxD+@Tp$=9v-cZ4jcp=KLFo1AXs!g7_|Rq zTHMgl$Q*;F&ICCv^Sc0f-~An0(V5lK3^u6iYV$4AW?}*@V?d++e345KAlhV@$uN^4 z)U_a;1J=Q<3152^JJWc;+1%zPWr%McbGyF#~pCfqe#n;)^(07M;%fJ+%F7!SBW zX+$ld5^p15Egd_5;EG`H#1U1ScjHXZLF%9B=d+dRAh0lBk%_NZp zR8SpYx&TXm?IC$@We9@AUqr0*rfKsn8MNdA>*&b=%)eL`_&FmtvSiuMulMioEsehe zzuww!^Tgb#zL;z6eQNiB$~e^LVfNeO`c_R``Il!VnE=v2 z84x-CGMe%F9UQ3RhxY((?0W&OK=Eagt<+w8n;gt3(j2$#6i9|gEehsAM!_T()Eq)TAc@u-Jk>YVxHeFvQxTw( zYmja>XwyP*q#(2}7y4m&Bv-j*;OFoSVEcAU(kcJJ6g6hNO`c?FfZOPT!~3hB@tk@T zT7X%gZO`Dgy!a@g3%(T$MY5};A3X5|*0J;=5Nc8|Kc91`_{`XpV5GZx9q){T#WDP5 z8jd%@Hu=CZh@}Y?<~ryiEWtDhljN`vs|X-WgH2IrN~k)3=jaGecpeD^y|Y-Puq9Z zW&LhLxb@wsKQhN1OY)U=fu!p&$$)&ZZ*3yIa+w0}_6G%uYfxJC1%!>;4QX;(<m7RDF|Vc zydMWZIW^#%3k6+kh+Ytn0`n;&0JsrIcNd&=p?H+}*xMwB&sl@Z#HE*uuQb}`9+I8i z`gn(DsFl9vV!n87xTDOyuo-W#^zNZ$o8%>JxJq%%Zy_W4_~P(T^$lZ%t8x3-WMi>u z4XlQ~TC4$lp7TDs7y z>=sdRi5z897^tcQ!l8!@wR%?z^-{(d`&cMQw`%4Ip<)Ay3zQ5oC%(?@g;tbR#mSY_ zDN%CndA8-~`5yFUtwI%rj&U%BFzwOF7m_w0GKRC@gqQy>mIKdu^#CFhFkq0BXDEo? z6zzLtCuTsO0TfVVFy^xng({^65t~tf8;id5#%w8LwN~7!Wx;iibKLOSR;N+|Zx9yi z;EgJxy)RX86mB47m-f<{mJk{it8>)il+qm{9Zs$ZTJ)Rb>>`%g#quH@7iI68ll(-9 z{yzFayF=^!mtJ1>NyOq(#gS=L^_vsdM%|;mx%A7U^v(S{&EnVCrLWnN=M{hZ$dwbN ze}(iYA`27~f)E!cc)}=7b$%JA?{hd9!2&GVbos!D5czg$FVY2Y{wrTpIKYY@VzV{| zxxk^C&0KRGlseBJ$w*5)6!HX`)?BQqI}cbbs?q86ijJ+}K*FNql~kv&fjJr?PIF8O_W4Jmc+>j6VBTy>(-G zZw=T%0RP=nP*VC_2!7==ii}73z!(vNwsVFffaB&bpFQak4+44GW*xRW0dzNk(}fDa zE`rmM0CWU=Fof}|Y@kxZ?z3scrZnbB(~?U6u{Oy)!*mkK-0J9A5ceCQgwT{YE)V1c zOggv*(!zp-nF575D<#ZOuJplgy>U^c$~t%D!E&?YLfxdkE7uDhEhb`e7T=kY7nwxY z{Cl?H+b^J0=}MPr!SW)z-gZY9x``_H!)L#R>!)3|?C@-8ImZ-r*f;*an!Y^{%KZDk z8`W5;7=>CzG-H&dnW?t=Ovy-tFvgfcLXlgk)W-JNeKtjmB%7gTw5~&Lxn{fA)or?H zr(B|F2`yc=3#x6{X+FQ#qwntzlbY$7=e*B3uX8_-C~hr3=f==cmZ5U*vT2jnb@to4 z=fBRAbx1LR%vzM>xs)+EaJl0j{|JAYa-!m#(Y^T&O3z*GM89qmPulTm4~yN{j%AP~ zD=PBw0`nSVnFdq%1J1YEch-SXWu>J1^lJ2B~N-C9;gWI@?}mzh(O2Jc+rNR=lv1s_T$Wq%AxF3#;A35ou8yjfHQST4d-BBK2>L(~s?Z+j4dlXg)-$aAqJ;W~8Als7K#>bdo2MUmzpZYl($oVzab8rS9 zhz)BZZEq7<^{RqD1Bsi z{eM!uK|G-WFNaBza|U(1Qp)^26Y|{H!N;^tl~!g`nX6lD=ZGZi(IRd@QR4bq--I#g z)3G&&irELG^9s}M)+OfIFbc7tI zpGS;xG%Ge~XK^%}G$-hB-f}W_T2idD=zZu=+N)7A$CyU?Q}i2Kq~dTkkfDX zNW*;SYpz~Uc7fqHX4{#oT^f&@{V)|*oyK{G3nS^64toN(V4QU1a@8bFB*#X`7wF~W zd8J#z!_QKuoD9{QrCKWu$Sh_g7oGBAj})H^tS~lEv(Otnwv}klRevGL2gh~d{L42x z^?Ft`sSn#cVMTToI#=3&RVsgWbQ_$+sIUhb@&FCg>>%NiwLY?-o0cw)$DiN+DE`2j zSxSv;W`?&GzCAsZ-xJz(-oa|B?cocI4Lr%2?b_N`7w&0=#5LlX{}c!peAEGD8>q=s z*pc9q!+GX0PK+Cpd2n(CdNZ89x%ga_2HT*zDs#t7RI7`+VwneJZmQ7lQm=)wyy+}g zd(RP<73RZn`8bbx(!sb+#3HckWR*I}?qJjZ5w?Z?;Ir)P{=$an3l^85YUS(@B%Yx6 z*Xo21Ca#a&$7bx?L_1iJ*?o7e#l?ouI(JN>%dBu>FP+RB81z+T{BVW+j>e8U>=9!f zh^O;#oz77lkqz+|vR6MDsN?W0W9{1R2@!OH&)f72Q5@+J^`knzR0~@`w9u6q3T{U8 zs&eCv%COtgG4aBu2i8`8;{QktZr7eHQjB^>EvxCWCG7Cdfs6Hw9kz@U({j6f(504+E4YK@aX0N+SYtDbN3^ zNtf9dZh4yj9#KofzSk8~E=-pQbSUN{1=$t9?Ra#O{X+}Yxk9`a0>Fge19J@6E~+DR+>dViLL8J>%taU%Q4ncxt)=_!A{Mmf$`m!6-;1b zKk*_4Ssk8H^Ghi=U5(cIomylFh0r>+skqX%vr^6qZ+)OPan5DV7NyJe{;5f&eP5Xp zqtV~(I>UHsIHlnQ)Yb<_;M1+2{AMG=F>0}r>ML6jH`I?9aF;(1k4I=N0Tt7ny2u@N zeN0>%*|vN_vnvWW5ML>4BA;q?C#K{(aeeIlUNrV>al- z>-?0^*hS6LSt2Rzo*9}rSymUyJL2em(ZqYhp)#{V=lZ&(@cFC852Dwr_nqCCu>)|Z zxX~9+JH;9MoB1;fJ=9VxUPh*Er`FADpy^{|@ku=0V*V9j)}D3SYWSAQ)1oPjz1urB z+i)fOGV1Gu9hs3Gb=dgVv$I3(-S+b<>947al}<`u9*}Fn3k0rdrW_czY(P{tC7etu zWZcj3#X1Y3-H#Xt`@kgd6LuS~Rp#1_>s_g4`}OAb{GH|P=@TH{Q?B=`aiDFpSJ}A= zhvp9~i?3>JLL^RYe~VXWS7#UG8--dXuGr3+ndzFkj+-kXt{Orv<1&+i#+LsioG6VuZx?8;^gfG{IB&PXmg#H!tKGyFWPOB)xj>_hnb>&spB=bQ*Y* zIP3K>%PUVE&WjXeQhPPgTquNL?j!Ed_z9;K4m4(KGlc!l;Dli6n=->ud3c~PALi^o zJQ$~ge;(Z!NW8?}dqRB-XUu^i8YROrwI7;PCLWVq zzrv^>vt_M75!5c2*<8F-cNVzf97SGJVwU+&i6atx*;Pp-XN>)qFVJd#9IAQcc z{6{_0MsGm4RGZWI(vhcBiXM6e?OIf*KU$Xl6y` zMOvr#7SHB{o6q7JhOP5to2!i&j)|*Es8t$?x7LX6YVUl%wK640fZU5E&W0V{mS$S+ zM@f;~Z&nxx?tL?W6%05`>%Gv(LDvr0UNQ~$G93vrko5Flb|erDMHS6tCmD6Jf3|N= zXm|Zqur*eEez}e~PZmW@iU^9FWj1N3LcFk3cyJ2OfZIw5{6nt7%LvJg2t#ph!a^JgOUXO&X3+0c$Dm(kFRkY9xP5nM zTYmM6nsIJ#;09{vRrBE)i1U~QQnFqRlcS*URi^dPkD@~%c(Vb$Y6_c_Q9rgdHGE;$ z;X{o0{}7rMi}DVTWa^C^9n3-!xP_{~ovJTr{pU)ZA6{#op0)PzmARD36|^H_V|#vc z%>G^U)2T@|8<+pGyEF;CZp`(&%^ZA{ohs{}B6S5uRT5tXY5N*Q=9;MH`o>#7a|7qq zVHyJ{AT+F(eA7`5?JQ;%N}KV0H{1L+sQzo)*(d_Zp`o+eqq$aFjEpEm0}sn^a-pAO)Cti(+?B}m7Sr` zpV&0lS)A_4_WhyP%Spo5FTGx!O8vIwGTD(~F|+HzxM|&PMca7&4l>v{7RkngZiMNY z1%+XaBu(Bn_nZ;M5`8q=$?-M%$BTa(8m{o{?B|CReND?sr0_pFX5z+D=YgghT6Z~_ z;yeG?SRmy=QLMwe3O8v@A8m=jkW6D>43^_iyc7&b9)8UxO`HeJ5jYCjv@p1y5Zs+& zkvyPD+$`ZP-XG{2VdT@z8TFMQLuzzHOWUVRS?s0U;8Jj>l<>0@`)m42x+2QmH8sVJg&myq4Di<(T>yWQw zJB_%*IPyc)ple9Wp0tRjV;4WB*kIh zEZepEVqu`|n?$`c`f0m`cf7vxv^n`I=`!xMS~YDMV@9#X$&6~w=*%;X?+lQIcl7Ux zNbB+69B1nK)fGG3NwVyu)OI3I;8lnr+D~EGvW%U?>#p*!(XNajowId2_|@*BqMc4# z86jCT&wO4(1kXNfBusS{n%##p$Fj+tIH07TQgz#C(5`mBjsW!UpWO!50iFluCECK{ zhe{1VGW+nel&o9;p5Qhcd?uTC`iZyvK#}e2-O=KH<5))X%R)n=&0&^XiRLJHhj*jX zatwS!Ri1$tZXknA?RZrmA)?F{q^tMJUcD}qJ_1=5I|=|%1 z2d=X3v@#AolFxju-Mppc471P_+)YZol|40he`e{D7_$qp-$#d6gs^+}28{aOBeq+MRMEPjKdXNe3uumb8^x>j1@1EID z?m6nM4$I{9btxiLWFzP>NtsH{A~6{s?UyraswN{%awqzz4Q;o%dMzl;xCa5^^hJ=N z*|;8@NIO6WkP2@}2+d9w{@>gL-{ic4;R11;b*+C-u*;(G6f^r}b*rxs{fg&Kf1W7{ z>TEne*Ly+R$$CjF`WAj`7kgRX=P%XN|MM|E&|K@mhl;Egk2qgFB))aJ;v2LAZ1TNVILO+oaW@Z?QX2<9Hi^ z56EdFUbo;TrPdE5DImx#lJ@rAn2$by{jbqROlXo>YjYHIz5=&L;a-prpqqM|bbhDe z4N_i7-vcE^m+rgs&g=|HIH>i`RZ{|dSe-9CH)$+5@8U4}6%^TAsn6n!3Ke_WHo|X~ zL=Q43tx7aCj=7yw9>*B##sKz??#bEV`=VjdpH$)U8$|S*#0{VqEQ{K?0xy>o^9@pe z3O*2G(;_^bZw!ly2U+oqXrWM)`{B^hQ(-Fd7Im@UXAXEy4<(R<8iEyN|AP&B~T9G@C(OwWJ(Lohm5~Im%7V^5BdN{hY}%+`;K<^C-W^*SiA? zfTbtHgxZ*!VKnz{Swir<^%9{@M2&LWzlfezfCVj}14@q)CfSGp z5wcnAwH9q?ZR0jMxg!e>A$VCU+53H?9mCqaawhp8#47cqGtA?W|9Qa~X;_nIwa2Ba zpSiB5;E%12($#SsP4(nu2LF zYiIa^3&a@s+E0QpsZ(YgGPd|I{fh{7L)0FiJyE^>g8hnpiaSf9Y~4fLfEv#?;c1ZP zLSrcGivzjC#;Xd-FPGHqZ2!)EFj#hmso1fn!BF<2pDar5a5v6w9`>oKUU_q#AK)(# z^Im>eP&TbIujgiU<;mcnQ@+KXW-9KI?=ErrZW&u)6_=2Gx<|G3#N-mW)d_!~yW0&)dm?MaUe0H-*Zj7*8k*6XJN8tQi_{s= zpb0QD+%$@84;tZ+o(d$6~jE9@pZM-?$}hiUdsshqJnPvlFeqt$_t z*4IL~ybWfGSD!*cyZw?+*2*)_pFl%d))H0@oTg^}SDBYQ^$hpN*R;;(S+_496X;D< z3S8`zVIid@xnoldGk@Ali<3 z;+kK<+vGwmwHzB}<-GE#t&v*PoDDxrj?FL$+ z>X2Dj?xi4&Nlsg)#A4Ero7lSB51(qxiZc-4w}bO}KG5kJljy&#VL`T5 z!wm$AlOH7idJs=cOq?0Aq;zes@8Qko_m^nm8cUU)K0}q~@yQddLO-^1*8GYK!PMr{ zF&gu+DOFan#Ovrz`HKHdio%6xzxkL(ah}B$Blmqch`}>m-f8r>a)E)5+f8W{B`ku* z@)jI`AT0E9hn~x=xa)v7KSs=Yp=s|;O0=`Wc~30L z#-CI0TsCw#-i8!Ut~J*t6Y4=zCOK#L0AWDDBP~9XMs|QcLJn3JqSlW?T2{QU*mQF9 zB`Tm|%5*lb-3@r2ZmfGkL|OmljEd_h(=&58OY3`e)9v9K>aY2}{!#Iq{zaGazUf-f zBLAAskibjf5t<{~NltZ3R%p3#WG}+}9sw)mw#GrO$Sm3t@ea)?k!!`57%e{C)j~AO zO|weiyki@TF^}*}A~qRWBn$NuWnF%Akioc^S6u42=HmMeZ~q`y>t!KM1zdrw=Pp}! zLR)-RK}9kZWF16f2j&3lKn0KhSyDnXR5Z}9N@rQUt#%VQztdc58;sHW_RP@z*SEfo z$=F#=m#7jlxh((gyTR3uuQ31c79Faby?3+UR>M#|>M;pF7{&{Ndv8k04^!?x(xxS4 zM%LQuhl)F?Tp!)rn(&Tt;Lr`Y!SJ8mIeoM|9g*$2hjJ?u=i@DqtHG81B zi{48(d8F6yJrn>)RTsyOd=KBGFdgh_%OR8#$m@t(M``zNU6a<;V}gow4J5FIx67O& z&~bQ-vP)6-iHgfKp~P)){nIh)K>7xs&D2_EfIvDlE0~2(1pGmSoaL{=#%S`k~o@OeOSyT!6?QS4yx0nO$8%x)9F{((Y;N$ z>jB~!7)0g;!kV;6kyool#f(Y`y?G_`eG#4Sl4rWUd6d2-td#Y-)t&%iIxmbe7&J5l<)8 ze8g}&&C}NSXlUY;%-xK4q4~>Ziz{r?fX%hGq*od1bTE$Hw@VJ!gKR(Frrs4n7DT@I z>-ulviE$d3m^q;GEgJ!k-akRMo6Oik*T3qjngFihDpI5X(Jw5A8lu}8z1Hz{TNXS{ zSGQ~3#epwXE_IU&_5W)8+gB@PRr=LFOhA>+S$ufC>w9VPBOM=fiX{kGgMyqYRk2BoPSR>%ehLR&F|906ijcTY-T$YtMim^!aVlj`z zsx((DoGkqkc=SbusRHts#S@?Pk*>ksm_nGt6XoDi9wN>!(^B)as$BG3>0Tgfq9mh` z24Ke!Bf6L`H6}CxHY)q`S-L>{!SV}0!UhC($c>*&7?reS?x1Wo0t}yf2SK!cubQla z2d60coIcJf_az}D8`af`g+ypaL11%4smoANSc+d>Et|ne^lJzq*Rw2*E?@TNlf@ot zY`b<;QZhLMLIrU4Rzq~ht!A@(6Jjz3@Pyc0_15kwp+3N45+?H4xNWjCW@5F4lGHRZ z(!#q1F%#VoX$G({KTB_=7zO`~1!?;lh`z4EL*+VR6uBkyIRjji#Wf3r_JtM~Jp@3s z7fZ1qg=e|-fR}=J4Ipfl@GF0SZ+1iyA=)$52C{xFzfcIoap7NH3`2KAePlz)k!Q4D>Fn?MX()}@7YXR;}A^equ)=;@XN9Z zEV~_pZ*JAQfkL=~^W0`HF6;y$e)UBvHo>@|`ZkfyAHxU&W+SyA0j)9vH=oLWq0fq1 z==EM0x)wfvSEU1_M(^ooz)4QvniaICxY9A1*8+{&j%jQ~NCjkFsM17GXs3j@uMLD|I*f89 zoyQz#6qB*Rji;Ji=qTB)jer7`uday$U8-$>RIBlUKRB9NginY}@J{8{-+bz*n3`g_ z+ddo#5S?QT{5Tf16s^C~W%Jcty;_B`v|2 o+>tt-4=F^C82G2rr)ofW6*
Pull requests @@ -144,7 +144,9 @@ export default class Default extends Component { "cssnext-Light" )}>
} diff --git a/docs/src/modules/Footer/index.js b/docs/src/modules/Footer/index.js index ce4aa80..4f0fa3f 100644 --- a/docs/src/modules/Footer/index.js +++ b/docs/src/modules/Footer/index.js @@ -20,7 +20,7 @@ export default class Footer extends Component { {" is brought to you by "} @MoOx {" & "} - + some other contributors .

@@ -37,7 +37,7 @@ export default class Footer extends Component { {" | "} Edit this page diff --git a/docs/src/modules/Header/index.js b/docs/src/modules/Header/index.js index f9b47f3..ca0aa3c 100644 --- a/docs/src/modules/Header/index.js +++ b/docs/src/modules/Header/index.js @@ -47,10 +47,13 @@ export default class Header extends Component {
- + Support - + GitHub diff --git a/docs/src/modules/playground/index.js b/docs/src/modules/playground/index.js index 7748522..3ec191a 100644 --- a/docs/src/modules/playground/index.js +++ b/docs/src/modules/playground/index.js @@ -40,7 +40,8 @@ function playground(opts) { opts.console.innerHTML = "

" + "If you think it's a bug, please " + - "
report it." + + "" + + "report it." + "
cssnext v" + cssnextVersion + "
" // use createTextNode to escape html entities diff --git a/package.json b/package.json index 65aab95..2e642be 100644 --- a/package.json +++ b/package.json @@ -3,17 +3,11 @@ "version": "2.3.0", "description": "Use tomorrow’s CSS syntax, today", "keywords": [ - "css", - "w3c", - "cssnext", - "preprocessor", - "postprocessor", - "rework", "postcss", "postcss-plugin", - "autoprefixer", - "babel", - "transpiler" + "css", + "w3c", + "cssnext" ], "author": "Maxime Thirouin", "license": "MIT", From 4c31cabccc6415cf228ccf484cf8b43d0e7a522d Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Mon, 4 Jan 2016 00:18:45 +0100 Subject: [PATCH 24/25] Docs: Better migration guide for postcss-cssnext with custom plugins and cssnano included poke @magsout --- docs/content/postcss.md | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/docs/content/postcss.md b/docs/content/postcss.md index 98a4fbc..9674b46 100644 --- a/docs/content/postcss.md +++ b/docs/content/postcss.md @@ -61,7 +61,7 @@ If you were using cssnext with default options, you might just need this: ```console $ npm uninstall cssnext [--save[-dev]] -$ npm install postcss postcss-import postcss-url postcss-reporter postcss-browser-reporter postcss-cssnext [--save[-dev]] +$ npm install postcss postcss-import postcss-url postcss-cssnext postcss-browser-reporter postcss-reporter [--save[-dev]] ``` With the previous lines you might thing that you are going backward by having a @@ -73,15 +73,23 @@ and previous default cssnext behavior. ##### [postcss-cli](https://www.npmjs.com/package/postcss-cli) +```console +$ npm install postcss-cli --save-dev +``` + Here is an example of the json config you might use with something like ``$ postcss-cli -c postcss.config.json``. -```json +```js { "use": [ "postcss-import", "postcss-url", - "postcss-cssnext" + "postcss-cssnext", + // add your "plugins" here + // ... + // and if you want to compress + // "cssnano", "postcss-browser-reporter", "postcss-reporter", ] @@ -90,6 +98,11 @@ Here is an example of the json config you might use with something like ##### [grunt-postcss](https://www.npmjs.com/package/grunt-postcss) +```console +$ npm uninstall grunt-cssnext --save-dev +$ npm install grunt-postcss --save-dev +``` + ```js grunt.initConfig({ postcss: { @@ -98,6 +111,10 @@ grunt.initConfig({ require("postcss-import")(), require("postcss-url")(), require("postcss-cssnext")(), + // add your "plugins" here + // ... + // and if you want to compress + // require("cssnano")(), require("postcss-browser-reporter")(), require("postcss-reporter")(), ] @@ -111,6 +128,11 @@ grunt.initConfig({ ##### [gulp-postcss](https://www.npmjs.com/package/gulp-postcss) +```console +$ npm uninstall gulp-cssnext --save-dev +$ npm install gulp-postcss --save-dev +``` + ```js var gulp = require('gulp') var postcss = require('gulp-postcss') @@ -122,6 +144,10 @@ gulp.task('css', function () { require("postcss-import")(), require("postcss-url")(), require("postcss-cssnext")(), + // add your "plugins" here + // ... + // and if you want to compress + // require("cssnano")(), require("postcss-browser-reporter")(), require("postcss-reporter")(), ])) @@ -132,6 +158,11 @@ gulp.task('css', function () { ##### [postcss-loader](https://www.npmjs.com/package/postcss-loader) +```console +$ npm uninstall cssnext-loader --save-dev +$ npm install postcss-loader --save-dev +``` + ```js module.exports = { module: { @@ -147,6 +178,10 @@ module.exports = { require("postcss-import")({ addDependencyTo: webpack }), require("postcss-url")(), require("postcss-cssnext")(), + // add your "plugins" here + // ... + // and if you want to compress, + // just use css-loader option that already use cssnano under the hood require("postcss-browser-reporter")(), require("postcss-reporter")(), ] From 25131d66deab20280c83f504fdcb863e87fd6a3a Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Mon, 4 Jan 2016 00:24:34 +0100 Subject: [PATCH 25/25] Fix test related to postcss-color-rgba-fallback update --- src/__tests__/fixtures/features/color-rgba.expected.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/fixtures/features/color-rgba.expected.css b/src/__tests__/fixtures/features/color-rgba.expected.css index 013f935..6fdb8b8 100644 --- a/src/__tests__/fixtures/features/color-rgba.expected.css +++ b/src/__tests__/fixtures/features/color-rgba.expected.css @@ -1,5 +1,5 @@ .foo { - background: #99DD99; + background: #99dd99; background: rgba(153, 221, 153, 0.8); border: solid 1px #646667; border: solid 1px rgba(100,102,103,.3);