├── .gitignore ├── .mailmap ├── .sass-lint.yml ├── .sassdocrc ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── docs ├── CHANGELOG.html ├── CONTRIBUTING.html ├── LICENSE.html ├── a-config.html ├── assets │ ├── img │ │ └── favicon.ico │ └── webpack │ │ ├── app.min.js │ │ ├── app_styles.min.css │ │ ├── common.min.js │ │ ├── runtime.min.js │ │ └── search.min.js ├── colors.html ├── contrast.html ├── index.html ├── search-data.json ├── search.html └── util.html ├── gulpfile.js ├── package.json ├── sass ├── _api.scss ├── _color.scss ├── _config.scss ├── _contrast.scss ├── _pow.scss └── _utils.scss ├── test ├── scss │ ├── _api.scss │ ├── _config.scss │ ├── _contrast.scss │ ├── _pow.scss │ ├── _utils.scss │ └── test.scss └── test_sass.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | **/.DS_Store 2 | .sass-cache 3 | node_modules 4 | gh-pages 5 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Miriam Suzanne Eric M Suzanne 2 | Miriam Suzanne E. Miriam Suzanne 3 | -------------------------------------------------------------------------------- /.sass-lint.yml: -------------------------------------------------------------------------------- 1 | # See https://github.com/sasstools/sass-lint/tree/develop/docs/rules 2 | # ------------------------------------------------------------------ 3 | 4 | # Rules 5 | rules: 6 | # Extends 7 | extends-before-declarations: 2 8 | extends-before-mixins: 2 9 | placeholder-in-extend: 2 10 | 11 | # Mixins 12 | mixins-before-declarations: 2 13 | 14 | # Line Spacing 15 | one-declaration-per-line: 2 16 | empty-line-between-blocks: 2 17 | single-line-per-selector: 2 18 | 19 | # Disallows 20 | no-color-keywords: 2 21 | no-color-literals: 0 22 | no-css-comments: 2 23 | no-debug: 2 24 | no-duplicate-properties: 2 25 | no-empty-rulesets: 2 26 | no-extends: 0 27 | no-ids: 2 28 | no-important: 2 29 | no-invalid-hex: 2 30 | no-mergeable-selectors: 1 31 | no-misspelled-properties: 2 32 | no-qualifying-elements: 2 33 | no-trailing-zero: 2 34 | no-transition-all: 0 35 | no-url-protocols: 2 36 | no-vendor-prefixes: 2 37 | no-warn: 0 38 | 39 | # nesting 40 | force-attribute-nesting: 2 41 | force-element-nesting: 2 42 | force-pseudo-nesting: 2 43 | 44 | # Style Guide 45 | border-zero: 2 46 | brace-style: 2 47 | clean-import-paths: 48 | - 2 49 | - leading-underscore: false 50 | filename-extension: false 51 | empty-args: 2 52 | function-name-format: 2 53 | hex-length: 2 54 | hex-notation: 2 55 | indentation: 2 56 | leading-zero: 57 | - 2 58 | - include: true 59 | mixin-name-format: 2 60 | nesting-depth: 61 | - 2 62 | - max-depth: 3 63 | placeholder-name-format: 2 64 | property-sort-order: 2 65 | quotes: 2 66 | shorthand-values: 2 67 | url-quotes: 2 68 | variable-for-property: 0 69 | variable-name-format: 2 70 | zero-unit: 2 71 | 72 | # Inner Spacing 73 | space-after-bang: 2 74 | space-after-colon: 2 75 | space-after-comma: 2 76 | space-before-bang: 2 77 | space-before-brace: 2 78 | space-before-colon: 2 79 | space-between-parens: 2 80 | 81 | # Final Items 82 | final-newline: 2 83 | trailing-semicolon: 2 84 | -------------------------------------------------------------------------------- /.sassdocrc: -------------------------------------------------------------------------------- 1 | theme: 'herman' 2 | dest: docs/ 3 | src: sass/ 4 | 5 | display: 6 | access: 7 | - public 8 | 9 | groups: 10 | 'Public API': 11 | a-config: Configuration 12 | colors: Accessing Colors 13 | contrast: Contrast Utilities 14 | util: Tint & Shade 15 | 16 | herman: 17 | sass: 18 | includepaths: ['sass'] 19 | includes: ['color'] 20 | extraDocs: 21 | - name: 'Changelog' 22 | path: CHANGELOG.md 23 | - name: 'Contributing' 24 | path: CONTRIBUTING.md 25 | - name: 'MIT License' 26 | path: LICENSE 27 | extraLinks: 28 | - name: 'Accoutrement Init' 29 | url: 'http://oddbird.net/accoutrement-init/' 30 | - name: 'Accoutrement Layout' 31 | url: 'http://oddbird.net/accoutrement-layout/' 32 | - name: 'Accoutrement Scale' 33 | url: 'http://oddbird.net/accoutrement-scale/' 34 | - name: 'Accoutrement Type' 35 | url: 'http://oddbird.net/accoutrement-type/' 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | sudo: false 5 | notifications: 6 | slack: 7 | rooms: 8 | secure: x2ev3OA2zr4tFDemF5D05J1tr0us49Qpf9maJ26C/JGYfRJNYKWnRwTPx7K/ONlMfw4KO4+/kFOWs4V1xoMzWSxHqgvqBVhdQ+v79hZqs7MEqzpTOG5c+5DkkWq2vOG1lfvTdqBG89D7MVsVBKjREzfK450S5HsECelzWh2DlFk= 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Accoutrement-Color Changelog 2 | ============================ 3 | 4 | 2.3.1 - 04/04/18 5 | ---------------- 6 | - BUGFIX: Fix typo in recursive `$function` lookup 7 | 8 | 9 | 2.3.0 - 04/03/18 10 | ---------------- 11 | - NEW: `$functions` map allows you to name/capture first-class functions 12 | in the latest versions of Sass, and call them by name in the `$colors` map 13 | 14 | 15 | 2.2.3 - 04/02/18 16 | ---------------- 17 | - BUGFIX: Support first-class functions (Sass 3.5+) 18 | 19 | 20 | 2.2.2 - 09/22/17 21 | ---------------- 22 | - BUGFIX: `color` function no longer chokes on self-reference 23 | in custom-palettes 24 | 25 | 26 | 2.2.1 - 09/13/17 27 | ---------------- 28 | - INTERNAL: Simplify get-function logic 29 | - DOCS: Fix broken source link 30 | 31 | 32 | 2.2.0 - 09/05/17 33 | ---------------- 34 | - DOCS: Update theme, organize, and expand examples 35 | - NEW: Added (private) `pow()` functions, 36 | so that MathSass is no longer a dependency for color-contrast calculations 37 | - NEW: Support upper or lowercase for WCAG contrast checks in `contrast-ratio`, 38 | e.g. 'aa'/'aaa', or 'AA'/'AAA' 39 | - NEW: Support first-class functions 40 | 41 | 42 | 2.1.2 - 08/26/17 43 | ---------------- 44 | - Docs: Update Herman, and simplify publication 45 | 46 | 47 | 2.1.1 - 05/21/17 48 | ---------------- 49 | - Docs: Remove unused mixin Sassdoc comment 50 | 51 | 52 | 2.1.0 - 03/08/17 53 | ---------------- 54 | - Support first-class functions in Sass 3.5. 55 | - Add `merge-colors` function, 56 | and `add-colors` mixin 57 | to combine individual color palettes. 58 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing to Accoutrement 2 | ============================ 3 | 4 | Bug reports and feature requests are welcome, 5 | but code is even better! 6 | 7 | In all cases, 8 | we ask you to follow the 9 | [Sass community guidelines](http://sass-lang.com/community-guidelines). 10 | 11 | 12 | Development 13 | ----------- 14 | 15 | Set up your environment 16 | with the appropriate development dependencies: 17 | 18 | ``` 19 | yarn 20 | ``` 21 | 22 | As you work... 23 | 24 | - Add or update any appropriate unit tests 25 | in the `test` directory, 26 | and make sure all tests are passing with `npm test` 27 | - Add your changes to the [changelog](CHANGELOG.md) 28 | - Update or add inline documentation 29 | using [SassDoc][sassdoc] as appropriate, 30 | and compile the docs with `gulp sassdoc` 31 | 32 | [sassdoc]: http://sassdoc.com/ 33 | 34 | 35 | Committing 36 | ---------- 37 | 38 | Linting, testing, and documentation 39 | should be done before every commit: 40 | 41 | ``` 42 | npm run commit 43 | ``` 44 | 45 | They can also be triggered individually: 46 | 47 | ``` 48 | # lint 49 | gulp sasslint 50 | 51 | # test with mocha/true, and compile ag-test CSS 52 | npm test 53 | 54 | # compile docs 55 | gulp sassdoc 56 | ``` 57 | 58 | Optionally use `npm run test-libsass` for js-only tests, 59 | or `rake test` for ruby-only environments. 60 | 61 | Once you've fixed any final errors or typos, 62 | commit your changes, and submit a pull request! 63 | 64 | 65 | Pull Requests 66 | ------------- 67 | 68 | We use the `master` branch for production-ready code, 69 | and side-branches for everything in-progress 70 | or up-for-debate. 71 | 72 | When submitting a patch via pull request: 73 | 74 | - Write a clear, descriptive commit message 75 | - Keep it simple: one bug fix or feature per pull request 76 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 OddBird 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Accoutrement-Color 2 | ================== 3 | 4 | **Sass color-palette management by [OddBird][oddbird]…** 5 | 6 | - Organize all your colors into a single map, or set of maps 7 | - Document color relationships directly in the code 8 | - Automate [WCAG-appropriate][wcag] contrast checking 9 | - Generate color-palette documentation with [Herman][Herman] 10 | 11 | [oddbird]: http://oddbird.net/ 12 | [wcag]: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef 13 | 14 | OddBird's Accoutrement toolkits are designed around the idea 15 | that code should be meaningful to both humans and machines – 16 | opening the door for automation, 17 | while improving or maintaining readability. 18 | These tools integrate with [Herman][Herman], 19 | our automated living pattern-library generator 20 | built on [SassDoc][SassDoc]. 21 | 22 | [Herman]: http://oddbird.net/herman/ 23 | [SassDoc]: http://sassdoc.com/ 24 | 25 | 26 | **Other Accoutrement include…** 27 | 28 | - [Init](http://oddbird.net/accoutrement-init/) 29 | provides lightweight browser-normalization. 30 | - [Scale](http://oddbird.net/accoutrement-scale/) 31 | helps manage scale patterns like font-sizes, margins, and gutters. 32 | - [Type](http://oddbird.net/accoutrement-type/) 33 | provides webfont management tools, 34 | and other typography helpers. 35 | - [Layout](http://oddbird.net/accoutrement-layout/) 36 | provides layout utilities such as 37 | box-sizing, intrinsic ratios, z-index management, 38 | named media-queries, and a clearfix. 39 | 40 | 41 | Quick Start: Colors 42 | ------------------- 43 | 44 | Install the package with npm or yarn: 45 | 46 | ```bash 47 | npm install accoutrement-color 48 | yarn add accoutrement-color 49 | ``` 50 | 51 | Import the library: 52 | 53 | ```scss 54 | @import '/accoutrement-color/sass/color'; 55 | ``` 56 | 57 | Establish your color palette: 58 | 59 | ```scss 60 | $colors: ( 61 | // set explicit colors 62 | 'brand-pink': hsl(330, 85%, 62%), 63 | 'brand-light': #ddf, 64 | 'brand-dark': #224, 65 | 66 | // reference existing colors 67 | 'background': 'brand-light', 68 | 'border': 'brand-dark', 69 | 70 | // make adjustments as needed, using color functions 71 | 'link': 'brand-pink' ('shade': 25%, 'desaturate': 15%), 72 | ); 73 | ``` 74 | 75 | Access your colors from anywhere: 76 | 77 | ```scss 78 | .example { 79 | border-color: color('border'); 80 | } 81 | ``` 82 | 83 | You can also define your colors in smaller maps, 84 | and then add them to the global `$colors` variable 85 | using the `merge-color()` function, 86 | or `add-colors()` mixin. 87 | 88 | ```scss 89 | $brand: ( 90 | 'brand-pink': hsl(330, 85%, 62%), 91 | 'brand-light': #ddf, 92 | 'brand-dark': #224, 93 | ); 94 | 95 | $patterns: ( 96 | 'background': 'brand-light', 97 | 'border': 'brand-dark', 98 | 'link': 'brand-pink' ('shade': 25%), 99 | ); 100 | 101 | // merge everything into the main $colors map… 102 | @include add-colors($brand, $patterns); 103 | ``` 104 | 105 | We'll also help you calculate WCAG-appropriate color contrasts: 106 | 107 | ```scss 108 | a:hover { 109 | // set a background, and get well-contrasted text 110 | @include contrasted('link'); 111 | 112 | // or return a contrasting color for use anywhere… 113 | border-color: contrast('background'); 114 | } 115 | ``` 116 | -------------------------------------------------------------------------------- /docs/CHANGELOG.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Changelog | Accoutrement: Color Documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 30 | 31 |
32 |
33 | 34 | 40 | 41 | 42 |
43 | Accoutrement: Color 44 | 45 | 2.3.1 46 | 47 |
48 |
49 | 50 |
51 | 52 | 168 | 169 | 170 |
171 | 172 | 177 | 178 | 179 |
180 | 181 |
182 |

Accoutrement-Color Changelog

183 |

2.3.1 - 04/04/18

184 |
    185 |
  • BUGFIX: Fix typo in recursive $function lookup
  • 186 |
187 |

2.3.0 - 04/03/18

188 |
    189 |
  • NEW: $functions map allows you to name/capture first-class functions 190 | in the latest versions of Sass, and call them by name in the $colors map
  • 191 |
192 |

2.2.3 - 04/02/18

193 |
    194 |
  • BUGFIX: Support first-class functions (Sass 3.5+)
  • 195 |
196 |

2.2.2 - 09/22/17

197 |
    198 |
  • BUGFIX: color function no longer chokes on self-reference 199 | in custom-palettes
  • 200 |
201 |

2.2.1 - 09/13/17

202 |
    203 |
  • INTERNAL: Simplify get-function logic
  • 204 |
  • DOCS: Fix broken source link
  • 205 |
206 |

2.2.0 - 09/05/17

207 |
    208 |
  • DOCS: Update theme, organize, and expand examples
  • 209 |
  • NEW: Added (private) pow() functions, 210 | so that MathSass is no longer a dependency for color-contrast calculations
  • 211 |
  • NEW: Support upper or lowercase for WCAG contrast checks in contrast-ratio, 212 | e.g. ‘aa’/‘aaa’, or ‘AA’/‘AAA’
  • 213 |
  • NEW: Support first-class functions
  • 214 |
215 |

2.1.2 - 08/26/17

216 |
    217 |
  • Docs: Update Herman, and simplify publication
  • 218 |
219 |

2.1.1 - 05/21/17

220 |
    221 |
  • Docs: Remove unused mixin Sassdoc comment
  • 222 |
223 |

2.1.0 - 03/08/17

224 |
    225 |
  • Support first-class functions in Sass 3.5.
  • 226 |
  • Add merge-colors function, 227 | and add-colors mixin 228 | to combine individual color palettes.
  • 229 |
230 | 231 |
232 | 233 |
234 |
235 |
236 |
237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | -------------------------------------------------------------------------------- /docs/CONTRIBUTING.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Contributing | Accoutrement: Color Documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 30 | 31 |
32 |
33 | 34 | 40 | 41 | 42 |
43 | Accoutrement: Color 44 | 45 | 2.3.1 46 | 47 |
48 |
49 | 50 |
51 | 52 | 168 | 169 | 170 |
171 | 172 | 177 | 178 | 179 |
180 | 181 |
182 |

Contributing to Accoutrement

183 |

Bug reports and feature requests are welcome, 184 | but code is even better!

185 |

In all cases, 186 | we ask you to follow the 187 | Sass community guidelines.

188 |

Development

189 |

Set up your environment 190 | with the appropriate development dependencies:

191 |
yarn
192 | 
193 |

As you work…

194 |
    195 |
  • Add or update any appropriate unit tests 196 | in the test directory, 197 | and make sure all tests are passing with npm test
  • 198 |
  • Add your changes to the changelog
  • 199 |
  • Update or add inline documentation 200 | using SassDoc as appropriate, 201 | and compile the docs with gulp sassdoc
  • 202 |
203 |

Committing

204 |

Linting, testing, and documentation 205 | should be done before every commit:

206 |
npm run commit
207 | 
208 |

They can also be triggered individually:

209 |
# lint
210 | gulp sasslint
211 | 
212 | # test with mocha/true, and compile ag-test CSS
213 | npm test
214 | 
215 | # compile docs
216 | gulp sassdoc
217 | 
218 |

Optionally use npm run test-libsass for js-only tests, 219 | or rake test for ruby-only environments.

220 |

Once you’ve fixed any final errors or typos, 221 | commit your changes, and submit a pull request!

222 |

Pull Requests

223 |

We use the master branch for production-ready code, 224 | and side-branches for everything in-progress 225 | or up-for-debate.

226 |

When submitting a patch via pull request:

227 |
    228 |
  • Write a clear, descriptive commit message
  • 229 |
  • Keep it simple: one bug fix or feature per pull request
  • 230 |
231 | 232 |
233 | 234 |
235 |
236 |
237 |
238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | -------------------------------------------------------------------------------- /docs/LICENSE.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | MIT License | Accoutrement: Color Documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 30 | 31 |
32 |
33 | 34 | 40 | 41 | 42 |
43 | Accoutrement: Color 44 | 45 | 2.3.1 46 | 47 |
48 |
49 | 50 |
51 | 52 | 168 | 169 | 170 |
171 | 172 | 177 | 178 | 179 |
180 | 181 |
182 |

The MIT License (MIT)

183 |

Copyright © 2017 OddBird

184 |

Permission is hereby granted, free of charge, to any person obtaining a copy 185 | of this software and associated documentation files (the “Software”), to deal 186 | in the Software without restriction, including without limitation the rights 187 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 188 | copies of the Software, and to permit persons to whom the Software is 189 | furnished to do so, subject to the following conditions:

190 |

The above copyright notice and this permission notice shall be included in all 191 | copies or substantial portions of the Software.

192 |

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 193 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 194 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 195 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 196 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 197 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

198 | 199 |
200 | 201 |
202 |
203 |
204 |
205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /docs/a-config.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Configuration | Accoutrement: Color Documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 30 | 31 |
32 |
33 | 34 | 40 | 41 | 42 |
43 | Accoutrement: Color 44 | 45 | 2.3.1 46 | 47 |
48 |
49 | 50 |
51 | 52 | 168 | 169 | 170 |
171 | 172 | 177 | 178 | 179 |
180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 |
195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 |
204 |

Color Configuration

205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 |
216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 |
255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 |
270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 |
281 |

282 | 283 | 284 | 285 | 286 | 287 | $_LOCAL-COLOR-FUNCTIONS 288 | 289 | 290 | 291 | (map) 292 | 293 | 294 | 295 |

296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 |
306 | 307 |
308 | 309 | scss 310 | 311 | 312 | 313 |
314 | 315 | 316 | 317 | 318 |
$_LOCAL-COLOR-FUNCTIONS: ( // sass-lint:disable-line variable-name-format
 319 |   'tint',
 320 |   'shade',
 321 |   'contrast',
 322 | );
323 |
324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 |
334 |

These functions are defined internally, 335 | and can be called by name without first being captured 336 | using the Sass get-function() approach.

337 |

Don’t make changes to this map directly. 338 | You can add your own named functions in the $functions map.

339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 |
350 | 351 | 352 |
353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 |
374 | 375 |

376 | Related 377 | 378 |

379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 |
394 |

395 | 396 | 397 | $functions 399 | 400 | 401 | 402 | 403 |

404 | 405 | 406 |
407 | 408 | 409 | 410 | 411 |
412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 |
422 | 423 |

424 | Used By 425 | 426 |

427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 |
446 |

447 | @function 448 | 449 | _ac-color-get-function() 450 | 451 | 452 | 453 | [private] 454 |

455 | 456 | 457 |
458 | 459 | 460 | 461 | 462 | 463 |
464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 |
480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 |
495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 |
506 |

507 | 508 | 509 | 510 | 511 | 512 | $functions 513 | 514 | 515 | 516 | (map) 517 | 518 | 519 | 520 |

521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 |
531 | 532 |
533 | 534 | scss 535 | 536 | 537 | 538 |
539 | 540 | 541 | 542 | 543 |
$functions: () !default;
544 |
545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 |
555 |

Define any additional color functions required 556 | to generate relataionships in the $colors map. 557 | This is only necessary for newer versions of Sass, 558 | where functions are first-class, 559 | and can be captured using get-function($name).

560 |
$functions: (
 561 |   'darken': get-function('darken'),
 562 |   'lighten': get-function('lighten'),
 563 | );
 564 | 
565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 |
576 | 577 | 578 |
579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 |
600 | 601 |

602 | Related 603 | 604 |

605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 |
620 |

621 | 622 | 623 | $_LOCAL-COLOR-FUNCTIONS 625 | 626 | 627 | 628 | 629 |

630 | 631 | 632 |
633 | 634 | 635 | 636 | 637 |
638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 |
648 | 649 |

650 | Used By 651 | 652 |

653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 |
672 |

673 | @function 674 | 675 | _ac-color-get-function() 676 | 677 | 678 | 679 | [private] 680 |

681 | 682 | 683 |
684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 |
694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 |
710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 |
725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 |
736 |

737 | 738 | 739 | 740 | 741 | 742 | $colors 743 | 744 | 745 | 746 | 747 | 748 |

749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 |
759 | 760 |
761 | 762 | scss 763 | 764 | 765 | 766 |
767 | 768 | 769 | 770 | 771 |
$colors: () !default;
772 |
773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 |
783 |

A variable storing the map of 784 | all colors globally-avialble on your project. 785 | Any colors added to the $colors map will be accesible 786 | to the color() function by default.

787 |

Define each color with a name, base-value, 788 | and optional adjustments

789 |
$colors: (
 790 |   'color-name': <base-value>,
 791 |   'color-two': <base-value> ('<color-function>': '<arguments>'),
 792 |   // will return: function-name($base-value, $arguments...)
 793 | );
 794 | 
795 |
    796 |
  • Name your colors anything – from abstractions like brand-pink, 797 | to concrete patterns like button or widget-background.
  • 798 |
  • Base-values can be CSS-ready colors (hex, rgb, hsla), 799 | or references other colors in the map.
  • 800 |
  • Adjustments are a nested map of color functions and arguments, 801 | for adjusting colors directly in your palette.
  • 802 |
803 |

The color-names contrast-light and contrast-dark are special. 804 | Use those names to define the default light-and-dark options 805 | for our color-contrast tools. 806 | They default to white and black respectively.

807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 |
818 | 819 | 820 |
821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 |
839 |

840 | Examples 841 |

842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 |
860 |
861 | 862 | 863 |
864 | 865 |
866 | 867 | scss 868 | 869 | 870 | 871 | 872 | simple color definitions 873 | 874 | 875 |
876 | 877 | 878 | 879 | 880 |
$colors: (
 881 |   'brand-pink': hsl(330, 85%, 62%),
 882 |   'brand-light': #fff,
 883 |   'brand-dark': #222,
 884 | );
885 |
886 | 887 | 888 |
889 | 890 | 891 |
892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 |
910 |
911 | 912 | 913 |
914 | 915 |
916 | 917 | scss 918 | 919 | 920 | 921 | 922 | reference other colors 923 | 924 | 925 |
926 | 927 | 928 | 929 | 930 |
$colors: (
 931 |   'background': 'brand-light',
 932 |   'text': 'brand-dark',
 933 |   'link': 'brand-pink',
 934 | );
935 |
936 | 937 | 938 |
939 | 940 | 941 |
942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 |
960 |
961 | 962 | 963 |
964 | 965 |
966 | 967 | scss 968 | 969 | 970 | 971 | 972 | adjust referenced colors with any color function 973 | 974 | 975 |
976 | 977 | 978 | 979 | 980 |
$colors: (
 981 |   'focus': 'link' ('darken': 15%, 'desaturate': 15%),
 982 | );
983 |
984 | 985 | 986 |
987 | 988 | 989 |
990 | 991 | 992 |
993 | 994 | 995 | 996 | 997 | 998 | 999 |
1000 | 1001 |

1002 | Related 1003 | 1004 |

1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 |
1020 |

1021 | @function 1022 | 1023 | color() 1025 | 1026 | 1027 | 1028 | 1029 |

1030 | 1031 | 1032 |
1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 |
1045 |

1046 | @function 1047 | 1048 | contrast() 1050 | 1051 | 1052 | 1053 | 1054 |

1055 | 1056 | 1057 |
1058 | 1059 | 1060 | 1061 | 1062 |
1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 |
1073 | 1074 |

1075 | Used By 1076 | 1077 |

1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1096 |
1097 |

1098 | @mixin 1099 | 1100 | add-colors() 1102 | 1103 | 1104 | 1105 | 1106 |

1107 | 1108 | 1109 |
1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | 1131 |
1132 |

1133 | @function 1134 | 1135 | contrast() 1137 | 1138 | 1139 | 1140 | 1141 |

1142 | 1143 | 1144 |
1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1154 |
1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 |
1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 |
1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1196 |
1197 |

1198 | 1199 | @mixin 1200 | 1201 | 1202 | 1203 | add-colors() 1204 | 1205 | 1206 | 1207 | 1208 | 1209 |

1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 |
1224 |

Merge individual color maps into the global $colors variable, 1225 | in case you want to define colors in smaller groups 1226 | such as brand-colors, link-colors, etc 1227 | before merging them into a single global color-palette. 1228 | This can be useful for internal organization, 1229 | documentation with SassDoc, 1230 | or integration with our pattern-library generator: 1231 | Herman.

1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | 1242 |
1243 | 1244 | 1245 |
1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | 1255 | 1256 | 1257 | 1258 |
1259 | 1260 |

1261 | Parameters & Output 1262 | 1263 |

1264 | 1265 | 1266 | 1267 | 1268 | 1269 | 1270 | 1271 | 1272 | 1273 |
1274 |

1275 | 1276 | 1277 | $maps: 1278 | 1279 | 1280 | (map...) 1281 | 1282 |

1283 | 1284 | 1285 | 1286 |
1287 |

Pass any number of maps to be merged.

1288 | 1289 |
1290 | 1291 |
1292 | 1293 | 1294 | 1295 | 1296 | 1297 | 1298 | 1299 | 1300 | 1301 | 1302 | 1303 | 1304 | 1305 |
1306 |

1307 | 1308 | 1309 | {CSS output} 1310 | 1311 | 1312 | (code block) 1313 | 1314 |

1315 | 1316 | 1317 | 1318 |
1319 |
    1320 |
  • An updated global $colors variable, 1321 | with new maps merged in.
  • 1322 |
1323 | 1324 |
1325 | 1326 |
1327 | 1328 | 1329 | 1330 | 1331 | 1332 | 1333 | 1334 |
1335 | 1336 | 1337 | 1338 | 1339 | 1340 | 1341 | 1342 | 1343 |
1344 |

1345 | Example 1346 |

1347 | 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 1354 | 1355 | 1356 | 1357 | 1358 | 1359 | 1360 | 1361 | 1362 | 1363 | 1364 |
1365 |
1366 | 1367 | 1368 |
1369 | 1370 |
1371 | 1372 | scss 1373 | 1374 | 1375 | 1376 |
1377 | 1378 | 1379 | 1380 | 1381 |
$brand-colors: (
1382 |   'brand-dark': #222,
1383 |   'brand-pink': hsl(330, 85%, 62%),
1384 | );
1385 | 
1386 | $text-colors: (
1387 |   'text': 'brand-dark',
1388 |   'link': 'brand-pink',
1389 | );
1390 | 
1391 | @include add-colors($brand-colors, $text-colors);
1392 |
1393 | 1394 | 1395 |
1396 | 1397 | 1398 |
1399 | 1400 | 1401 |
1402 | 1403 | 1404 | 1405 | 1406 | 1407 | 1408 | 1409 | 1410 | 1411 |
1412 | 1413 |

1414 | Requires 1415 | 1416 |

1417 | 1418 | 1419 | 1420 | 1421 | 1422 | 1423 | 1424 | 1425 | 1426 | 1427 | 1428 | 1429 | 1430 | 1431 | 1432 | 1433 | 1434 | 1435 | 1436 | 1437 | 1438 | 1439 |
1440 |

1441 | @function 1442 | 1443 | merge-colors() 1445 | 1446 | 1447 | 1448 | 1449 |

1450 | 1451 | 1452 |
1453 | 1454 | 1455 | 1456 | 1457 | 1458 | 1459 | 1460 | 1461 | 1462 | 1463 | 1464 | 1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1471 | 1472 | 1473 | 1474 |
1475 |

1476 | 1477 | 1478 | $colors 1480 | 1481 | 1482 | 1483 | 1484 |

1485 | 1486 | 1487 |
1488 | 1489 | 1490 | 1491 | 1492 | 1493 | 1494 | 1495 | 1496 | 1497 | 1498 | 1499 |
1500 | 1501 | 1502 | 1503 | 1504 | 1505 | 1506 | 1507 | 1508 | 1509 | 1510 | 1511 | 1512 | 1513 | 1514 | 1515 | 1516 | 1517 |
1518 | 1519 | 1520 | 1521 | 1522 | 1523 | 1524 | 1525 | 1526 | 1527 | 1528 | 1529 | 1530 | 1531 | 1532 |
1533 | 1534 | 1535 | 1536 | 1537 | 1538 | 1539 | 1540 | 1541 | 1542 | 1543 |
1544 |

1545 | 1546 | @function 1547 | 1548 | 1549 | 1550 | merge-colors() 1551 | 1552 | 1553 | 1554 | 1555 | 1556 |

1557 | 1558 | 1559 | 1560 | 1561 | 1562 | 1563 | 1564 | 1565 | 1566 | 1567 | 1568 | 1569 | 1570 |
1571 |

Merge multiple color maps into a single map, 1572 | in case you want to define colors in smaller groups – 1573 | such as brand-colors, link-colors, etc. – 1574 | before merging them into a single map.

1575 |

This is like add-colors, 1576 | but returns the combined map 1577 | without assigning it to the $colors variable.

1578 | 1579 | 1580 | 1581 | 1582 | 1583 | 1584 | 1585 | 1586 | 1587 | 1588 |
1589 | 1590 | 1591 |
1592 | 1593 | 1594 | 1595 | 1596 | 1597 | 1598 | 1599 | 1600 | 1601 | 1602 | 1603 | 1604 |
1605 | 1606 |

1607 | Parameters & Return 1608 | 1609 |

1610 | 1611 | 1612 | 1613 | 1614 | 1615 | 1616 | 1617 | 1618 | 1619 |
1620 |

1621 | 1622 | 1623 | $maps: 1624 | 1625 | 1626 | (maps...) 1627 | 1628 |

1629 | 1630 | 1631 | 1632 |
1633 |

Pass any number of maps to be merged.

1634 | 1635 |
1636 | 1637 |
1638 | 1639 | 1640 | 1641 | 1642 | 1643 | 1644 | 1645 | 1646 | 1647 | 1648 |
1649 |

1650 | 1651 | 1652 | @return 1653 | 1654 | 1655 | (map) 1656 | 1657 |

1658 | 1659 | 1660 | 1661 |
1662 |

The merged map of colors.

1663 | 1664 |
1665 | 1666 |
1667 | 1668 | 1669 | 1670 | 1671 | 1672 | 1673 | 1674 | 1675 | 1676 | 1677 |
1678 | 1679 | 1680 | 1681 | 1682 | 1683 | 1684 | 1685 | 1686 |
1687 |

1688 | Example 1689 |

1690 | 1691 | 1692 | 1693 | 1694 | 1695 | 1696 | 1697 | 1698 | 1699 | 1700 | 1701 | 1702 | 1703 | 1704 | 1705 | 1706 | 1707 |
1708 |
1709 | 1710 | 1711 |
1712 | 1713 |
1714 | 1715 | scss 1716 | 1717 | 1718 | 1719 |
1720 | 1721 | 1722 | 1723 | 1724 |
$brand-colors: (
1725 |   'brand-dark': #222,
1726 |   'brand-pink': hsl(330, 85%, 62%),
1727 | );
1728 | 
1729 | $text-colors: (
1730 |   'text': 'brand-dark',
1731 |   'link': 'brand-pink',
1732 | );
1733 | 
1734 | $colors: merge-colors($brand-colors, $text-colors);
1735 |
1736 | 1737 | 1738 |
1739 | 1740 | 1741 |
1742 | 1743 | 1744 |
1745 | 1746 | 1747 | 1748 | 1749 | 1750 | 1751 | 1752 | 1753 | 1754 | 1755 | 1756 |
1757 | 1758 |

1759 | Used By 1760 | 1761 |

1762 | 1763 | 1764 | 1765 | 1766 | 1767 | 1768 | 1769 | 1770 | 1771 | 1772 | 1773 | 1774 | 1775 | 1776 | 1777 | 1778 | 1779 | 1780 |
1781 |

1782 | @mixin 1783 | 1784 | add-colors() 1786 | 1787 | 1788 | 1789 | 1790 |

1791 | 1792 | 1793 |
1794 | 1795 | 1796 | 1797 | 1798 | 1799 |
1800 | 1801 | 1802 | 1803 | 1804 | 1805 | 1806 | 1807 | 1808 | 1809 | 1810 | 1811 | 1812 | 1813 | 1814 | 1815 |
1816 | 1817 | 1818 | 1819 |
1820 |
1821 |
1822 |
1823 | 1824 | 1825 | 1826 | 1827 | 1828 | 1829 | 1830 | -------------------------------------------------------------------------------- /docs/assets/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddbird/accoutrement-color/850a0348e54391ce0b0bd0714f267422072e613a/docs/assets/img/favicon.ico -------------------------------------------------------------------------------- /docs/assets/webpack/app.min.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[5],{11:function(e,n){e.exports={colors:{"brand-colors":{"brand-orange":"#c75000","brand-blue":"#0d7fa5","brand-pink":"#aa0e5c"},"neutral-colors":{"light-gray":"#dedede",gray:"#555b5e",black:"#3b4042"},"theme-colors":{"theme-dark":"#0d7fa5","theme-light":"#cfe5ed",background:"#fff",text:"#3b4042","text-light":"#555b5e",action:"#aa0e5c",focus:"#0d7fa5",underline:"#eac3d6",border:"#555b5e","border-light":"#dedede",shadow:"rgba(85, 91, 94, 0.5)",callout:"#cfe5ed",slight:"#fafcfd",code:"#0d7fa5","code-shadow":"rgba(13, 127, 165, 0.2)"},"system-colors":{"contrast-light":"#fff","contrast-dark":"#3b4042"},"hljs-colors":{"hljs-comment":"#93a1a1","hljs-green":"#859900","hljs-cyan":"#2aa198","hljs-blue":"#268bd2","hljs-yellow":"#b58900","hljs-orange":"#cb4b16","hljs-red":"#dc322f","hljs-formula":"#eee8d5"},"demo-colors":{"brand-blue":"#0d7fa5","brand-pink":"#e2127a"},"demo-noncolors":{"light-gray":"#dedede",gray:"#555b5e",black:"#3b4042"}},ratios:{"text-ratios":{"line-height":1.4},"demo-ratios":{"line-height":1.4}},sizes:{"root-sizes":{root:"18px",responsive:"calc(1em + 0.125vw)",large:"calc(1rem + 0.5vw)",small:"0.9rem"},"text-sizes":{reset:"1rem",h1:"calc(1rem + 2vw)",h2:"calc(1rem + 1vw)",h3:"calc(1rem + 0.5vw)",quote:"calc(1rem + 0.5vw)",code:"0.9rem",footer:"0.9rem",search:"0.9rem"},"spacing-sizes":{rhythm:"1.4rem",gutter:"1.4rem","gutter-plus":"2.1rem","double-gutter":"2.8rem","flex-gutter":"calc(0.7rem + 2.5vw)",spacer:"calc(4.2rem + 2.5vw)","gutter-minus":"1.05rem",shim:"0.7rem","half-shim":"0.35rem","quarter-shim":"0.175rem"},"pattern-sizes":{"nav-underline":"4px","nav-icon":"28px","arrow-border":"8px","arrow-depth":"0.7rem","arrow-side":"1.4rem","font-preview":"24em","specimen-aa":"4.2rem","color-preview":"16em","color-swatch":"5.6rem","footer-logo":"2.8rem"},"layout-sizes":{page:"50rem","item-break":"40em","page-break":"50em","nav-break":"65em"},"demo-sizes":{root:"18px",xlarge:"3rem"}},fonts:{sans:{name:"Source Sans Pro",source:"https://fonts.google.com/specimen/Source+Sans+Pro",stack:["Helvetica Neue","Helvetica","Arial","sans-serif"]},code:{name:"Source Code Pro",source:"https://fonts.google.com/specimen/Source+Code+Pro",stack:["Consolas","Menlo","Monaco","Lucida Console","Liberation Mono","DejaVu Sans Mono","Bitstream Vera Sans Mono","Courier New","monospace","sans-serif"]},"demo-cdn":{name:"Source Code Pro",source:"https://fonts.google.com/specimen/Source+Code+Pro",stack:["Consolas","Menlo","Courier New","monospace","sans-serif"]},"demo-local":{name:"rockingham",normal:{path:"rockingham/rockingham-regular-webfont",local:"rockingham-regular-webfont"},bold:"rockingham/rockingham-bold-webfont",italic:"rockingham/rockingham-italic-webfont","bold italic":"rockingham/rockingham-bolditalic-webfont",stack:"fantasy",formats:["woff2","woff","ttf"]}}}},18:function(e,n,t){"use strict";(function(e){t.d(n,"c",function(){return i}),t.d(n,"a",function(){return s}),t.d(n,"b",function(){return o});var a=t(11),r=t.n(a),i=function(){var n=e("body");n.on("toggle:close",'[data-toggle="button"]',function(){var n=e(this).attr("aria-controls"),t=e('[data-target-id="'.concat(n,'"]'));e('[data-toggle="button"][aria-controls="'.concat(n,'"][aria-pressed="true"]')).attr("aria-pressed","false"),t.trigger("target:close")}),n.on("toggle:open",'[data-toggle="button"]',function(){var n=e(this),t=n.attr("aria-controls"),a=e('[data-target-id="'.concat(t,'"]')),r=e('[data-toggle="button"][aria-controls="'.concat(t,'"]')).not(n);n.data("toggle-synced")?r.filter('[data-toggle-synced="true"]').attr("aria-pressed","true"):r.filter('[aria-pressed="true"]').attr("aria-pressed","false"),n.attr("aria-pressed","true"),a.trigger("target:open")}),n.on("target:close",'[data-toggle="target"]',function(n){var t=e(this);e(n.target).is(t)&&t.attr("aria-expanded","false")});var t=function(n){var t=n.attr("data-target-id"),a=e('[data-toggle="button"][aria-controls="'.concat(t,'"][aria-pressed="true"]'));a.length?a.trigger("toggle:close"):n.trigger("target:close")};n.on("target:open",'[data-toggle="target"]',function(n){var t=e(this);e(n.target).is(t)&&t.attr("aria-expanded","true")}),n.on("click",'[data-toggle="button"]',function(n){n.preventDefault();var t=e(this);"true"===t.attr("aria-pressed")?t.trigger("toggle:close"):t.trigger("toggle:open")}),n.on("click",'[data-toggle="close"]',function(n){n.preventDefault();var a=e('[data-target-id="'.concat(e(this).attr("aria-controls"),'"]'));t(a)});n.on("click",function(n){e('[data-toggle="target"][aria-expanded="true"][data-auto-closing="true"]').each(function(a,r){!function(e,n){var a=n.attr("data-target-id"),r=e.closest('[aria-controls="'.concat(a,'"]')).length,i=document.contains(e.get(0)),s=!e.closest(n).length,o=n.attr("data-auto-closing-exception"),l=!!o&&e.closest(o).length;!r&&(n.data("auto-closing-on-any-click")||i&&s&&!l)&&t(n)}(e(n.target),e(r))})})},s=function(){var n=function(n){n.contentWindow.document.body&&(n.height=e(n.contentWindow.document).outerHeight(!0))},t=function(){e("iframe").each(function(){n(this)})};t(),e("iframe").on("load",function(){n(this)}),e(window).on("resize",t)},o=function(){var n=r.a&&r.a.sizes&&r.a.sizes["layout-sizes"]&&r.a.sizes["layout-sizes"]["nav-break"];if(n){var t=e("#nav"),a=e('[aria-controls="nav"]'),i=window.matchMedia("(min-width: ".concat(n,")")),s=function(e){e.matches?t.attr("aria-expanded","true"):t.attr("aria-expanded",a.attr("aria-pressed"))};s(i),i.addListener(s)}}}).call(this,t(16))},49:function(e,n,t){ 2 | /*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */ 3 | !function(e){"object"==typeof window&&window||"object"==typeof self&&self;(function(e){var n=[],t=Object.keys,a={},r={},i=/^(no-?highlight|plain|text)$/i,s=/\blang(?:uage)?-([\w-]+)\b/i,o=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,l="",c={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};function d(e){return e.replace(/&/g,"&").replace(//g,">")}function g(e){return e.nodeName.toLowerCase()}function u(e,n){var t=e&&e.exec(n);return t&&0===t.index}function m(e){return i.test(e)}function b(e){var n,t={},a=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return a.forEach(function(e){for(n in e)t[n]=e[n]}),t}function f(e){var n=[];return function e(t,a){for(var r=t.firstChild;r;r=r.nextSibling)3===r.nodeType?a+=r.nodeValue.length:1===r.nodeType&&(n.push({event:"start",offset:a,node:r}),a=e(r,a),g(r).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:r}));return a}(e,0),n}function p(e){function n(e){return e&&e.source||e}function a(t,a){return new RegExp(n(t),"m"+(e.case_insensitive?"i":"")+(a?"g":""))}!function r(i,s){if(i.compiled)return;i.compiled=!0;i.keywords=i.keywords||i.beginKeywords;if(i.keywords){var o={},l=function(n,t){e.case_insensitive&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof i.keywords?l("keyword",i.keywords):t(i.keywords).forEach(function(e){l(e,i.keywords[e])}),i.keywords=o}i.lexemesRe=a(i.lexemes||/\w+/,!0);s&&(i.beginKeywords&&(i.begin="\\b("+i.beginKeywords.split(" ").join("|")+")\\b"),i.begin||(i.begin=/\B|\b/),i.beginRe=a(i.begin),i.end||i.endsWithParent||(i.end=/\B|\b/),i.end&&(i.endRe=a(i.end)),i.terminator_end=n(i.end)||"",i.endsWithParent&&s.terminator_end&&(i.terminator_end+=(i.end?"|":"")+s.terminator_end));i.illegal&&(i.illegalRe=a(i.illegal));null==i.relevance&&(i.relevance=1);i.contains||(i.contains=[]);i.contains=Array.prototype.concat.apply([],i.contains.map(function(e){return function(e){e.variants&&!e.cached_variants&&(e.cached_variants=e.variants.map(function(n){return b(e,{variants:null},n)}));return e.cached_variants||e.endsWithParent&&[b(e)]||[e]}("self"===e?i:e)}));i.contains.forEach(function(e){r(e,i)});i.starts&&r(i.starts,s);var c=i.contains.map(function(e){return e.beginKeywords?"\\.?("+e.begin+")\\.?":e.begin}).concat([i.terminator_end,i.illegal]).map(n).filter(Boolean);i.terminators=c.length?a(c.join("|"),!0):{exec:function(){return null}}}(e)}function h(e,n,t,r){function i(e,n){var t=b.case_insensitive?n[0].toLowerCase():n[0];return e.keywords.hasOwnProperty(t)&&e.keywords[t]}function s(e,n,t,a){var r=a?"":c.classPrefix,i='')+n+s}function o(){_+=null!=E.subLanguage?function(){var e="string"==typeof E.subLanguage;if(e&&!a[E.subLanguage])return d(y);var n=e?h(E.subLanguage,y,!0,v[E.subLanguage]):w(y,E.subLanguage.length?E.subLanguage:void 0);E.relevance>0&&(x+=n.relevance);e&&(v[E.subLanguage]=n.top);return s(n.language,n.value,!1,!0)}():function(){var e,n,t,a;if(!E.keywords)return d(y);a="",n=0,E.lexemesRe.lastIndex=0,t=E.lexemesRe.exec(y);for(;t;)a+=d(y.substring(n,t.index)),(e=i(E,t))?(x+=e[1],a+=s(e[0],d(t[0]))):a+=d(t[0]),n=E.lexemesRe.lastIndex,t=E.lexemesRe.exec(y);return a+d(y.substr(n))}(),y=""}function g(e){_+=e.className?s(e.className,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(y+=e,null==n)return o(),0;var a=function(e,n){var t,a;for(t=0,a=n.contains.length;t")+'"');return y+=n,n.length||1}var b=N(e);if(!b)throw new Error('Unknown language: "'+e+'"');p(b);var f,E=r||b,v={},_="";for(f=E;f!==b;f=f.parent)f.className&&(_=s(f.className,"",!0)+_);var y="",x=0;try{for(var M,O,k=0;E.terminators.lastIndex=k,M=E.terminators.exec(n);)O=m(n.substring(k,M.index),M[0]),k=M.index+O;for(m(n.substr(k)),f=E;f.parent;f=f.parent)f.className&&(_+=l);return{relevance:x,value:_,language:e,top:E}}catch(e){if(e.message&&-1!==e.message.indexOf("Illegal"))return{relevance:0,value:d(n)};throw e}}function w(e,n){n=n||c.languages||t(a);var r={relevance:0,value:d(e)},i=r;return n.filter(N).forEach(function(n){var t=h(n,e,!1);t.language=n,t.relevance>i.relevance&&(i=t),t.relevance>r.relevance&&(i=r,r=t)}),i.language&&(r.second_best=i),r}function E(e){return c.tabReplace||c.useBR?e.replace(o,function(e,n){return c.useBR&&"\n"===e?"
":c.tabReplace?n.replace(/\t/g,c.tabReplace):""}):e}function v(e){var t,a,i,o,l,u=function(e){var n,t,a,r,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",t=s.exec(i))return N(t[1])?t[1]:"no-highlight";for(i=i.split(/\s+/),n=0,a=i.length;n/g,"\n"):t=e,l=t.textContent,i=u?h(u,l,!0):w(l),(a=f(t)).length&&((o=document.createElementNS("http://www.w3.org/1999/xhtml","div")).innerHTML=i.value,i.value=function(e,t,a){var r=0,i="",s=[];function o(){return e.length&&t.length?e[0].offset!==t[0].offset?e[0].offset"}function c(e){i+=""}function u(e){("start"===e.event?l:c)(e.node)}for(;e.length||t.length;){var m=o();if(i+=d(a.substring(r,m[0].offset)),r=m[0].offset,m===e){s.reverse().forEach(c);do{u(m.splice(0,1)[0]),m=o()}while(m===e&&m.length&&m[0].offset===r);s.reverse().forEach(l)}else"start"===m[0].event?s.push(m[0].node):s.pop(),u(m.splice(0,1)[0])}return i+d(a.substr(r))}(a,f(o),l)),i.value=E(i.value),e.innerHTML=i.value,e.className=function(e,n,t){var a=n?r[n]:t,i=[e.trim()];e.match(/\bhljs\b/)||i.push("hljs");-1===e.indexOf(a)&&i.push(a);return i.join(" ").trim()}(e.className,u,i.language),e.result={language:i.language,re:i.relevance},i.second_best&&(e.second_best={language:i.second_best.language,re:i.second_best.relevance}))}function _(){if(!_.called){_.called=!0;var e=document.querySelectorAll("pre code");n.forEach.call(e,v)}}function N(e){return e=(e||"").toLowerCase(),a[e]||a[r[e]]}e.highlight=h,e.highlightAuto=w,e.fixMarkup=E,e.highlightBlock=v,e.configure=function(e){c=b(c,e)},e.initHighlighting=_,e.initHighlightingOnLoad=function(){addEventListener("DOMContentLoaded",_,!1),addEventListener("load",_,!1)},e.registerLanguage=function(n,t){var i=a[n]=t(e);i.aliases&&i.aliases.forEach(function(e){r[e]=n})},e.listLanguages=function(){return t(a)},e.getLanguage=N,e.inherit=b,e.IDENT_RE="[a-zA-Z]\\w*",e.UNDERSCORE_IDENT_RE="[a-zA-Z_]\\w*",e.NUMBER_RE="\\b\\d+(\\.\\d+)?",e.C_NUMBER_RE="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BINARY_NUMBER_RE="\\b(0b[01]+)",e.RE_STARTERS_RE="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BACKSLASH_ESCAPE={begin:"\\\\[\\s\\S]",relevance:0},e.APOS_STRING_MODE={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},e.QUOTE_STRING_MODE={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},e.PHRASAL_WORDS_MODE={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.COMMENT=function(n,t,a){var r=e.inherit({className:"comment",begin:n,end:t,contains:[]},a||{});return r.contains.push(e.PHRASAL_WORDS_MODE),r.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|XXX):",relevance:0}),r},e.C_LINE_COMMENT_MODE=e.COMMENT("//","$"),e.C_BLOCK_COMMENT_MODE=e.COMMENT("/\\*","\\*/"),e.HASH_COMMENT_MODE=e.COMMENT("#","$"),e.NUMBER_MODE={className:"number",begin:e.NUMBER_RE,relevance:0},e.C_NUMBER_MODE={className:"number",begin:e.C_NUMBER_RE,relevance:0},e.BINARY_NUMBER_MODE={className:"number",begin:e.BINARY_NUMBER_RE,relevance:0},e.CSS_NUMBER_MODE={className:"number",begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},e.REGEXP_MODE={className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[e.BACKSLASH_ESCAPE,{begin:/\[/,end:/\]/,relevance:0,contains:[e.BACKSLASH_ESCAPE]}]},e.TITLE_MODE={className:"title",begin:e.IDENT_RE,relevance:0},e.UNDERSCORE_TITLE_MODE={className:"title",begin:e.UNDERSCORE_IDENT_RE,relevance:0},e.METHOD_GUARD={begin:"\\.\\s*"+e.UNDERSCORE_IDENT_RE,relevance:0},e.registerLanguage("bash",function(e){var n={className:"variable",variants:[{begin:/\$[\w\d#@][\w\d_]*/},{begin:/\$\{(.*?)}/}]},t={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,n,{className:"variable",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]}]};return{aliases:["sh","zsh"],lexemes:/\b-?[a-z\._]+\b/,keywords:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},contains:[{className:"meta",begin:/^#![^\n]+sh\s*$/,relevance:10},{className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0},e.HASH_COMMENT_MODE,t,{className:"string",begin:/'/,end:/'/},n]}}),e.registerLanguage("css",function(e){var n={begin:/[A-Z\_\.\-]+\s*:/,returnBegin:!0,end:";",endsWithParent:!0,contains:[{className:"attribute",begin:/\S/,end:":",excludeEnd:!0,starts:{endsWithParent:!0,excludeEnd:!0,contains:[{begin:/[\w-]+\(/,returnBegin:!0,contains:[{className:"built_in",begin:/[\w-]+/},{begin:/\(/,end:/\)/,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]}]},e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{className:"number",begin:"#[0-9A-Fa-f]+"},{className:"meta",begin:"!important"}]}}]};return{case_insensitive:!0,illegal:/[=\/|'\$]/,contains:[e.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/},{className:"selector-class",begin:/\.[A-Za-z0-9_-]+/},{className:"selector-attr",begin:/\[/,end:/\]/,illegal:"$"},{className:"selector-pseudo",begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"@(font-face|page)",lexemes:"[a-z-]+",keywords:"font-face page"},{begin:"@",end:"[{;]",illegal:/:/,contains:[{className:"keyword",begin:/\w+/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]}]},{className:"selector-tag",begin:"[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},{begin:"{",end:"}",illegal:/\S/,contains:[e.C_BLOCK_COMMENT_MODE,n]}]}}),e.registerLanguage("xml",function(e){var n={endsWithParent:!0,illegal:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],case_insensitive:!0,contains:[{className:"meta",begin:"",relevance:10,contains:[{begin:"\\[",end:"\\]"}]},e.COMMENT("\x3c!--","--\x3e",{relevance:10}),{begin:"<\\!\\[CDATA\\[",end:"\\]\\]>",relevance:10},{begin:/<\?(php)?/,end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0}]},{className:"tag",begin:"|$)",end:">",keywords:{name:"style"},contains:[n],starts:{end:"",returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:"|$)",end:">",keywords:{name:"script"},contains:[n],starts:{end:"<\/script>",returnEnd:!0,subLanguage:["actionscript","javascript","handlebars","xml"]}},{className:"meta",variants:[{begin:/<\?xml/,end:/\?>/,relevance:10},{begin:/<\?\w+/,end:/\?>/}]},{className:"tag",begin:"",contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},n]}]}}),e.registerLanguage("django",function(e){var n={begin:/\|[A-Za-z]+:?/,keywords:{name:"truncatewords removetags linebreaksbr yesno get_digit timesince random striptags filesizeformat escape linebreaks length_is ljust rjust cut urlize fix_ampersands title floatformat capfirst pprint divisibleby add make_list unordered_list urlencode timeuntil urlizetrunc wordcount stringformat linenumbers slice date dictsort dictsortreversed default_if_none pluralize lower join center default truncatewords_html upper length phone2numeric wordwrap time addslashes slugify first escapejs force_escape iriencode last safe safeseq truncatechars localize unlocalize localtime utc timezone"},contains:[e.QUOTE_STRING_MODE,e.APOS_STRING_MODE]};return{aliases:["jinja"],case_insensitive:!0,subLanguage:"xml",contains:[e.COMMENT(/\{%\s*comment\s*%}/,/\{%\s*endcomment\s*%}/),e.COMMENT(/\{#/,/#}/),{className:"template-tag",begin:/\{%/,end:/%}/,contains:[{className:"name",begin:/\w+/,keywords:{name:"comment endcomment load templatetag ifchanged endifchanged if endif firstof for endfor ifnotequal endifnotequal widthratio extends include spaceless endspaceless regroup ifequal endifequal ssi now with cycle url filter endfilter debug block endblock else autoescape endautoescape csrf_token empty elif endwith static trans blocktrans endblocktrans get_static_prefix get_media_prefix plural get_current_language language get_available_languages get_current_language_bidi get_language_info get_language_info_list localize endlocalize localtime endlocaltime timezone endtimezone get_current_timezone verbatim"},starts:{endsWithParent:!0,keywords:"in by as",contains:[n],relevance:0}}]},{className:"template-variable",begin:/\{\{/,end:/}}/,contains:[n]}]}}),e.registerLanguage("javascript",function(e){var n="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={className:"number",variants:[{begin:"\\b(0[bB][01]+)"},{begin:"\\b(0[oO][0-7]+)"},{begin:e.C_NUMBER_RE}],relevance:0},r={className:"subst",begin:"\\$\\{",end:"\\}",keywords:t,contains:[]},i={className:"string",begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE,r]};r.contains=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,a,e.REGEXP_MODE];var s=r.contains.concat([e.C_BLOCK_COMMENT_MODE,e.C_LINE_COMMENT_MODE]);return{aliases:["js","jsx"],keywords:t,contains:[{className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},{className:"meta",begin:/^#!/,end:/$/},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,{begin:/[{,]\s*/,relevance:0,contains:[{begin:n+"\\s*:",returnBegin:!0,relevance:0,contains:[{className:"attr",begin:n,relevance:0}]}]},{begin:"("+e.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.REGEXP_MODE,{className:"function",begin:"(\\(.*?\\)|"+n+")\\s*=>",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:n},{begin:/\(\s*\)/},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:t,contains:s}]}]},{begin://,subLanguage:"xml",contains:[{begin:/<\w+\s*\/>/,skip:!0},{begin:/<\w+/,end:/(\/\w+|\w+\/)>/,skip:!0,contains:[{begin:/<\w+\s*\/>/,skip:!0},"self"]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/\{/,excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:n}),{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:s}],illegal:/\[|%/},{begin:/\$[(.]/},e.METHOD_GUARD,{className:"class",beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"constructor",end:/\{/,excludeEnd:!0}],illegal:/#(?!!)/}}),e.registerLanguage("json",function(e){var n={literal:"true false null"},t=[e.QUOTE_STRING_MODE,e.C_NUMBER_MODE],a={end:",",endsWithParent:!0,excludeEnd:!0,contains:t,keywords:n},r={begin:"{",end:"}",contains:[{className:"attr",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE],illegal:"\\n"},e.inherit(a,{begin:/:/})],illegal:"\\S"},i={begin:"\\[",end:"\\]",contains:[e.inherit(a)],illegal:"\\S"};return t.splice(t.length,0,r,i),{contains:t,keywords:n,illegal:"\\S"}}),e.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],contains:[{className:"section",variants:[{begin:"^#{1,6}",end:"$"},{begin:"^.+?\\n[=-]{2,}$"}]},{begin:"<",end:">",subLanguage:"xml",relevance:0},{className:"bullet",begin:"^([*+-]|(\\d+\\.))\\s+"},{className:"strong",begin:"[*_]{2}.+?[*_]{2}"},{className:"emphasis",variants:[{begin:"\\*.+?\\*"},{begin:"_.+?_",relevance:0}]},{className:"quote",begin:"^>\\s+",end:"$"},{className:"code",variants:[{begin:"^```w*s*$",end:"^```s*$"},{begin:"`.+?`"},{begin:"^( {4}|\t)",end:"$",relevance:0}]},{begin:"^[-\\*]{3,}",end:"$"},{begin:"\\[.+?\\][\\(\\[].*?[\\)\\]]",returnBegin:!0,contains:[{className:"string",begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0,relevance:0},{className:"link",begin:"\\]\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0},{className:"symbol",begin:"\\]\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0}],relevance:10},{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}),e.registerLanguage("scss",function(e){var n={className:"variable",begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b"},t={className:"number",begin:"#[0-9A-Fa-f]+"};return e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{case_insensitive:!0,illegal:"[=/|']",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:"\\#[A-Za-z0-9_-]+",relevance:0},{className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0},{className:"selector-attr",begin:"\\[",end:"\\]",illegal:"$"},{className:"selector-tag",begin:"\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\b",relevance:0},{begin:":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)"},{begin:"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)"},n,{className:"attribute",begin:"\\b(z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\b",illegal:"[^\\s]"},{begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"},{begin:":",end:";",contains:[n,t,e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{className:"meta",begin:"!important"}]},{begin:"@",end:"[{;]",keywords:"mixin include extend for if else each while charset import debug media page content font-face namespace warn",contains:[n,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,t,e.CSS_NUMBER_MODE,{begin:"\\s[A-Za-z0-9_.-]+",relevance:0}]}]}}),e.registerLanguage("shell",function(e){return{aliases:["console"],contains:[{className:"meta",begin:"^\\s{0,3}[\\w\\d\\[\\]()@-]*[>%$#]",starts:{end:"$",subLanguage:"bash"}}]}}),e.registerLanguage("ruby",function(e){var n="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",t={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},a={className:"doctag",begin:"@[A-Za-z]+"},r={begin:"#<",end:">"},i=[e.COMMENT("#","$",{contains:[a]}),e.COMMENT("^\\=begin","^\\=end",{contains:[a],relevance:10}),e.COMMENT("^__END__","\\n$")],s={className:"subst",begin:"#\\{",end:"}",keywords:t},o={className:"string",contains:[e.BACKSLASH_ESCAPE,s],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:"%[qQwWx]?\\(",end:"\\)"},{begin:"%[qQwWx]?\\[",end:"\\]"},{begin:"%[qQwWx]?{",end:"}"},{begin:"%[qQwWx]?<",end:">"},{begin:"%[qQwWx]?/",end:"/"},{begin:"%[qQwWx]?%",end:"%"},{begin:"%[qQwWx]?-",end:"-"},{begin:"%[qQwWx]?\\|",end:"\\|"},{begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{begin:/<<(-?)\w+$/,end:/^\s*\w+$/}]},l={className:"params",begin:"\\(",end:"\\)",endsParent:!0,keywords:t},c=[o,r,{className:"class",beginKeywords:"class module",end:"$|;",illegal:/=/,contains:[e.inherit(e.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{begin:"<\\s*",contains:[{begin:"("+e.IDENT_RE+"::)?"+e.IDENT_RE}]}].concat(i)},{className:"function",beginKeywords:"def",end:"$|;",contains:[e.inherit(e.TITLE_MODE,{begin:n}),l].concat(i)},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[o,{begin:n}],relevance:0},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{className:"params",begin:/\|/,end:/\|/,keywords:t},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[r,{className:"regexp",contains:[e.BACKSLASH_ESCAPE,s],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r{",end:"}[a-z]*"},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(i),relevance:0}].concat(i);s.contains=c,l.contains=c;var d=[{begin:/^\s*=>/,starts:{end:"$",contains:c}},{className:"meta",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>)",starts:{end:"$",contains:c}}];return{aliases:["rb","gemspec","podspec","thor","irb"],keywords:t,illegal:/\/\*/,contains:i.concat(d).concat(c)}}),e.registerLanguage("yaml",function(e){var n="[a-zA-Z_][\\w\\-]*",t={className:"attr",variants:[{begin:"^[ \\-]*"+n+":"},{begin:'^[ \\-]*"'+n+'":'},{begin:"^[ \\-]*'"+n+"':"}]},a={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:"{{",end:"}}"},{begin:"%{",end:"}"}]}]};return{case_insensitive:!0,aliases:["yml","YAML","yaml"],contains:[t,{className:"meta",begin:"^---s*$",relevance:10},{className:"string",begin:"[\\|>] *$",returnEnd:!0,contains:a.contains,end:t.variants[0].begin},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!!"+e.UNDERSCORE_IDENT_RE},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"^ *-",relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:"true false yes no null",keywords:{literal:"true false yes no null"}},e.C_NUMBER_MODE,a]}})})(n)}()},81:function(e,n,t){var a,r,i;r=this,i=window.srcDoc,void 0===(a=function(e){!function(e,n){var t,a,r,i=!!("srcdoc"in document.createElement("iframe")),s="Polyfill may not function in the presence of the `sandbox` attribute. Consider using the `force` option.",o=/\ballow-same-origin\b/,l=function(e,n){var t=e.getAttribute("sandbox");"string"!=typeof t||o.test(t)||(n&&n.force?e.removeAttribute("sandbox"):n&&!1===n.force||(r(s),e.setAttribute("data-srcdoc-polyfill",s)))},c={compliant:function(e,n,t){n&&(l(e,t),e.setAttribute("srcdoc",n))},legacy:function(e,n,t){var a;e&&e.getAttribute&&(n?e.setAttribute("srcdoc",n):n=e.getAttribute("srcdoc"),n&&(l(e,t),a="javascript: window.frameElement.getAttribute('srcdoc');",e.contentWindow&&(e.contentWindow.location=a),e.setAttribute("src",a)))}},d=e;if(r=window.console&&window.console.error?function(e){window.console.error("[srcdoc-polyfill] "+e)}:function(){},d.set=c.compliant,d.noConflict=function(){return window.srcDoc=n,d},!i)for(d.set=c.legacy,a=document.getElementsByTagName("iframe"),t=a.length;t--;)d.set(a[t])}(e,i),r.srcDoc=e}.apply(n,[n]))||(e.exports=a)},82:function(e,n){ 4 | /*! matchMedia() polyfill addListener/removeListener extension. Author & copyright (c) 2012: Scott Jehl. Dual MIT/BSD license */ 5 | !function(){if(window.matchMedia&&window.matchMedia("all").addListener)return!1;var e=window.matchMedia,n=e("only all").matches,t=!1,a=0,r=[],i=function(n){clearTimeout(a),a=setTimeout(function(){for(var n=0,t=r.length;nh2:first-child,.text-block>h3:first-child{margin-top:0}.text-block h2{font-size:calc(1rem + 1vw);margin-bottom:.7rem}.text-block h3{font-size:calc(1rem + .5vw);font-weight:400;margin-bottom:.7rem}.text-block p,.text-block pre{margin-bottom:1.05rem}.text-block ol,.text-block ul{margin:0 1.4rem 1.05rem}.text-block li>p{margin:.7rem 0}.text-block blockquote{border-left:.35rem solid #dedede;font-size:calc(1rem + .5vw);margin-left:-1.4rem;padding-left:1.05rem}.text-block blockquote>p:not(:last-child){text-indent:-.4em}.text-block blockquote>p:not(:last-child):after,.text-block blockquote>p:not(:last-child):before{content:"\201C";color:#0d7fa5}.text-block blockquote>p:not(:last-child):after{content:"\201D"}.text-block blockquote cite{display:block;font-size:1rem;font-style:normal}.invert-colors{background-color:#0d7fa5;color:#fff}.invert-colors [href]:link,.invert-colors [href]:visited{color:inherit}::-webkit-input-placeholder{color:currentColor;opacity:.5}:-ms-input-placeholder,::-ms-input-placeholder{color:currentColor;opacity:.5}::placeholder{color:currentColor;opacity:.5}input{border:1px solid #dedede;color:inherit;font-size:.9rem;margin-bottom:.35rem;padding:.175rem .35rem;width:100%}input:focus{border-color:currentColor;outline:0}.search-heading{font-size:calc(1rem + 2vw)}.search-term{font-family:Source Code Pro,Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,sans-serif}.search-results{list-style:none}.search-result{margin:calc(.7rem + 2.5vw) 0}[data-result-field=contents]{color:#555b5e}.nav-subsection{-ms-flex:0 0 auto;flex:0 0 auto}.nav-subsection:last-of-type{-ms-flex:1 0 auto;flex:1 0 auto}.nav-subsection+.nav-item{border-top:1px solid;margin-top:2.8rem;padding-top:1.4rem}.nav-home{font-size:calc(1rem + .5vw);font-weight:700;margin-top:2.1rem}.nav-title{border-top:1px solid;font-weight:700;margin:2.8rem 0 1.4rem;padding-top:.175rem}.nav-item{list-style:none;margin:.35rem 0}[data-nav]:link,[data-nav]:visited{color:#fff;line-height:1.1;padding-bottom:.175rem;position:relative;text-decoration:none;transition:color .4s}[data-nav]:link:before,[data-nav]:visited:before{content:"";bottom:0;left:0;position:absolute;background:#cfe5ed;height:4px;-webkit-transform:scaleX(0);transform:scaleX(0);-webkit-transform-origin:center left;transform-origin:center left;transition:-webkit-transform .4s cubic-bezier(.22,.61,.36,1);transition:transform .4s cubic-bezier(.22,.61,.36,1);transition:transform .4s cubic-bezier(.22,.61,.36,1),-webkit-transform .4s cubic-bezier(.22,.61,.36,1);transition-delay:.2s;width:100%}[data-nav]:active:before,[data-nav]:focus:before,[data-nav]:hover:before,[data-nav][data-nav=is-active]:active:before,[data-nav][data-nav=is-active]:focus:before,[data-nav][data-nav=is-active]:hover:before,[data-nav][data-nav=is-active]:link:before,[data-nav][data-nav=is-active]:visited:before{content:"";-webkit-transform:scaleX(1);transform:scaleX(1);transition-delay:0s}.footer-credit{border-top:1px solid #cfe5ed;-ms-flex:0 0 auto;flex:0 0 auto;font-size:.9rem;line-height:1.4rem;padding-top:1.4rem}.footer-credit:after{clear:both;content:" ";display:block}.footer-credit span{display:block;overflow:hidden;white-space:nowrap}.footer-icon:link,.footer-icon:visited{color:inherit;float:left;margin-right:.35rem}.footer-link:link,.footer-link:visited{font-weight:700;-webkit-text-decoration-color:transparent;text-decoration-color:transparent}.footer-link:active,.footer-link:focus,.footer-link:hover{-webkit-text-decoration-color:currentColor;text-decoration-color:currentColor}.breadcrumb{background:#cfe5ed;padding:.7rem calc(.7rem + 2.5vw)}.breadcrumb a,.breadcrumb span,.breadcrumb strong{display:inline-block}.project-links{display:-ms-flexbox;display:flex;-ms-flex-pack:end;justify-content:flex-end;margin-left:0;margin-right:0}@media (max-width:49.99em){.project-links{margin-bottom:.7rem}}.project-link-item{display:-ms-flexbox;display:flex;list-style:none}.project-link-item+.project-link-item{margin-left:.7rem}.project-link:link,.project-link:visited{border:1px solid #aa0e5c;border-radius:1.4rem;padding:.35rem 1.4rem;text-align:center;text-decoration:none;transition:background-color .4s}.project-link:active,.project-link:focus,.project-link:hover{background-color:#aa0e5c;color:#fff}.item{margin-bottom:calc(4.2rem + 2.5vw)}[data-item-section]{margin-bottom:2.1rem}[data-item-section=header] .code-block,[data-item-section=header] .text-block{margin-bottom:.7rem}.item-title{font-size:calc(1rem + 1vw)}.item-subtitle{border-bottom:1px solid #dedede;color:#555b5e;font-weight:400;margin-bottom:.7rem}.item-subtitle-main{letter-spacing:.05em;text-transform:uppercase}.item-subtitle-main:not(:last-child):after{content:": "}.item-subtitle-supplement{letter-spacing:0;padding-left:.35rem}.alias-title,.item-name,.item-subtitle-supplement,.item-type,.item-value{font-family:Source Code Pro,Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,sans-serif}.alias-title,.item-name,.item-type,.item-value{display:inline-block}.item-note,.item-type,.item-value,.value-type{color:#555b5e;display:inline-block;font-weight:400}.alias{color:#555b5e;font-style:italic}.alias-title{font-style:normal;font-weight:bolder}.param-list{margin-bottom:.7rem}.param-title{color:#555b5e;font-size:calc(1rem + .5vw)}.param-details{margin-top:.35rem}@media (min-width:40em){.param-details{margin-left:1.4rem}}@media (min-width:40em){.requires-wrapper{display:-ms-flexbox;display:flex;margin-bottom:2.1rem}.requires-wrapper [data-item-section]{-ms-flex:1 1 40%;flex:1 1 40%;margin-bottom:0;max-width:100%}.requires-wrapper [data-item-section]:first-child{margin-right:1.4rem}}.color-palette{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:-.7rem}@supports (display:grid){.color-palette{display:grid;grid-auto-rows:auto;grid-gap:1.4rem;grid-template-columns:repeat(auto-fit,minmax(16em,1fr));margin:0}}.color-preview{-ms-flex-align:stretch;align-items:stretch;display:-ms-flexbox;display:flex;-ms-flex:1 0 16em;flex:1 0 16em;-ms-flex-direction:column;flex-direction:column;font-size:.9rem;margin:.7rem}@supports (display:grid){.color-preview{margin:0}}.color-swatch{border:1px solid #555b5e;height:5.6rem;min-width:5.6rem;position:relative}.color-overlay,.transparency-grid{bottom:0;left:0;position:absolute;right:0;top:0}.transparency-grid{background:url('data:image/svg+xml;utf8,') 50% repeat scroll;background-size:.5em .5em;left:50%}.color-name,.color-value{display:block;padding:.35rem}.color-name-option{display:inline-block}.color-value{background-color:#fafcfd;border-radius:.175rem;box-shadow:inset 0 0 .175rem rgba(13,127,165,.2);color:#555b5e;font-weight:400;margin-top:.175rem;white-space:nowrap}.hljs-comment,.hljs-quote{color:#93a1a1}.hljs-addition,.hljs-keyword,.hljs-selector-tag{color:#859900}.hljs-doctag,.hljs-literal,.hljs-meta .hljs-meta-string,.hljs-number,.hljs-regexp,.hljs-string{color:#2aa198}.hljs-name,.hljs-section,.hljs-selector-class,.hljs-selector-id,.hljs-title{color:#268bd2}.hljs-attr,.hljs-attribute,.hljs-class .hljs-title,.hljs-template-variable,.hljs-type,.hljs-variable{color:#b58900}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-meta .hljs-keyword,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-subst,.hljs-symbol{color:#cb4b16}.hljs-built_in,.hljs-deletion{color:#dc322f}.hljs-formula{background:#eee8d5}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bolder}.code-block{-ms-flex-align:stretch;align-items:stretch;display:-ms-flexbox;display:flex;-ms-flex:1 1 20em;flex:1 1 20em;-ms-flex-direction:column;flex-direction:column;max-height:16.8rem;max-width:100%;overflow:hidden}.code-header{background-color:#cfe5ed;color:#3b4042;-ms-flex:0 0 auto;flex:0 0 auto;padding:0 .7rem}.code-description:before{content:" \2013 "}.hljs-pre,.text-block pre{background-color:#fafcfd;border:1px solid #cfe5ed;color:#0d7fa5;-ms-flex:1 1 auto;flex:1 1 auto;-ms-flex-wrap:wrap;flex-wrap:wrap}.hljs-pre code,.text-block pre code{padding:.7rem}.example{margin-bottom:1.4rem}.example-code{-ms-flex-align:stretch;align-items:stretch;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;overflow:hidden}.example-render{border:1px solid #dedede;border-top:0;padding:.7rem}.sassdoc{overflow:visible}.font-specimen{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:1.4rem -.7rem 0}@supports (display:grid){.font-specimen{display:grid;grid-auto-rows:auto;grid-gap:1.4rem;grid-template-columns:repeat(auto-fit,minmax(24em,1fr));margin:1.4rem 0 0}}[data-specimen-face]{-ms-flex-align:stretch;align-items:stretch;display:-ms-flexbox;display:flex;-ms-flex:1 0 24em;flex:1 0 24em;-ms-flex-direction:column;flex-direction:column;font-size:.9rem;margin:.7rem}@supports (display:grid){[data-specimen-face]{margin:0}}[data-specimen=sample]{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:justify;justify-content:space-between}[data-specimen=lorem]{-ms-flex:1 1 auto;flex:1 1 auto;padding-left:.7rem}[data-specimen=lorem] span{display:block}[data-specimen=aa]{-ms-flex:0 1 auto;flex:0 1 auto;font-size:4.2rem;padding-left:.175rem}[data-sassdoc=icon-preview]{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));margin:0 -.7rem}[data-sassdoc-icon]{margin:1.4rem .7rem;min-width:7rem}[data-sassdoc-icon] [data-icon]{height:calc(1rem + 2vw);width:calc(1rem + 2vw);margin-bottom:.7rem}[data-sassdoc=icon-info]{font-size:.9rem}.sizes{width:100%}.sizes td{overflow:hidden;padding:.175rem .7rem;vertical-align:baseline}.sizes td+td{border-left:1px solid #dedede}.sizes.is-large{display:block}.sizes.is-large tbody{display:block;max-width:100%}.sizes.is-large tr{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.sizes.is-large td{display:block;-ms-flex:0 0 auto;flex:0 0 auto;text-align:left}.sizes.is-large td+td{border-left:0}.sizes.is-large .size-name,.sizes.is-large .size-value{padding-bottom:0}.sizes.is-large .size-viz{-ms-flex:0 0 100%;flex:0 0 100%;max-width:none}.sizes.is-large .is-text,.sizes.is-large .size-overflow{padding-bottom:.7rem}@media (max-width:39.99em){.sizes,.sizes tbody{display:block}.sizes tbody{max-width:100%}.sizes tr{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.sizes td{display:block;-ms-flex:0 0 auto;flex:0 0 auto;text-align:left}.sizes td+td{border-left:0}.sizes .size-name,.sizes .size-value{padding-bottom:0}.sizes .size-viz{-ms-flex:0 0 100%;flex:0 0 100%;max-width:none}.sizes .is-text,.sizes .size-overflow{padding-bottom:.7rem}}.size{max-width:100%}.size-name,.size-value{color:#555b5e;-ms-flex:0 1 5ch;flex:0 1 5ch;font-size:.9rem;white-space:nowrap}.size-viz{max-width:0;overflow-x:auto;width:100%}.size-viz.is-text{overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}.size-overflow{max-width:100%;overflow-x:auto}.size-bar{background-color:#555b5e;background-image:linear-gradient(270deg,#eac3d6 1px,transparent 0,transparent),linear-gradient(270deg,hsla(0,0%,87%,.5) 1px,transparent 0,transparent),linear-gradient(270deg,hsla(0,0%,87%,.25) 1px,transparent 0,transparent);background-position:0 100%;background-repeat:repeat-x;background-size:100px 75%,10px 50%,5px 25%;border-radius:.175rem;display:inline-block}.size-text{line-height:1.2}.ratio-base{background-color:#cfe5ed}.ratio-base .size-bar{background-color:#aa0e5c} -------------------------------------------------------------------------------- /docs/assets/webpack/runtime.min.js: -------------------------------------------------------------------------------- 1 | !function(r){function e(e){for(var t,p,a=e[0],c=e[1],f=e[2],l=0,s=[];l 4 | 5 | 6 | 7 | 8 | 9 | 10 | Accessing Colors | Accoutrement: Color Documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 30 | 31 |
32 |
33 | 34 | 40 | 41 | 42 |
43 | Accoutrement: Color 44 | 45 | 2.3.1 46 | 47 |
48 |
49 | 50 |
51 | 52 | 168 | 169 | 170 |
171 | 172 | 177 | 178 | 179 |
180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 |
195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 |
204 |

Accessing Colors

205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 |
216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 |
255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 |
270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 |
281 |

282 | 283 | @function 284 | 285 | 286 | 287 | color() 288 | 289 | 290 | 291 | 292 | 293 |

294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 |
308 |

The primary function for 309 | accessing colors in your palette, 310 | or making adjustments on the fly.

311 |

This is more than a wrapper for map-get($colors, $x). 312 | It also handles internal color-references, recursion, 313 | and functional color-adjustments. 314 | It has access to the global $colors map by default, 315 | but you can also pass in arbitrary color-palette maps as well.

316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 |
327 | 328 | 329 |
330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 |
343 | 344 |

345 | Parameters & Return 346 | 347 |

348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 |
358 |

359 | 360 | 361 | $color: 362 | 363 | 364 | (string | list) 365 | 366 |

367 | 368 | 369 | 370 |
371 |

The name of a color in your palette, 372 | or a color description in the 373 | map configuration format.

374 | 375 |
376 | 377 |
378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 |
387 |

388 | 389 | 390 | $palette: 391 | 392 | $colors 393 | (map) 394 | 395 |

396 | 397 | 398 | 399 |
400 |

Optional map containing the source color-palette. 401 | Defaults to the global $colors map.

402 | 403 |
404 | 405 |
406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 |
417 |

418 | 419 | 420 | @return 421 | 422 | 423 | (color) 424 | 425 |

426 | 427 | 428 | 429 |
430 |

A calculated css-ready color, 431 | based on your global color palette and adjustments.

432 | 433 |
434 | 435 |
436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 |
447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 |
456 |

457 | Example 458 |

459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 |
477 |
478 | 479 | 480 |
481 | 482 |
483 | 484 | scss 485 | 486 | 487 | 488 |
489 | 490 | 491 | 492 | 493 |
$colors: (
494 |   'background': #eee,
495 |   'text': #222,
496 | );
497 | 
498 | html {
499 |   background: color('background');
500 |   color: color('text');
501 | }
502 |
503 | 504 | 505 | 506 |
507 | 508 |
509 | 510 | css 511 | 512 | 513 | 514 | 515 | compiled 516 | 517 | 518 |
519 | 520 | 521 | 522 | 523 |
html {
524 |   background: #eee;
525 |   color: #222;
526 | }
527 | 
528 |
529 | 530 | 531 |
532 | 533 | 534 |
535 | 536 | 537 |
538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 |
546 | 547 | 548 |
549 | 550 |

551 | Requires 552 | 553 |

554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 |
577 |

578 | @function 579 | 580 | _ac-color-get-function() 581 | 582 | 583 | 584 | [private] 585 |

586 | 587 | 588 |
589 | 590 | 591 | 592 | 593 | 594 |
595 | 596 | 597 | 598 | 599 | 600 |
601 | 602 |

603 | Used By 604 | 605 |

606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 |
625 |

626 | @function 627 | 628 | contrast() 630 | 631 | 632 | 633 | 634 |

635 | 636 | 637 |
638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 |
660 |

661 | @mixin 662 | 663 | contrasted() 665 | 666 | 667 | 668 | 669 |

670 | 671 | 672 |
673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 |
691 |

692 | @function 693 | 694 | luminance() 696 | 697 | 698 | 699 | 700 |

701 | 702 | 703 |
704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 |
722 |

723 | @function 724 | 725 | tint() 727 | 728 | 729 | 730 | 731 |

732 | 733 | 734 |
735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 |
753 |

754 | @function 755 | 756 | shade() 758 | 759 | 760 | 761 | 762 |

763 | 764 | 765 |
766 | 767 | 768 | 769 | 770 | 771 |
772 | 773 | 774 | 775 |
776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 |
789 | 790 | 791 | 792 |
793 |
794 |
795 |
796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Accoutrement: Color Documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 30 | 31 |
32 |
33 | 34 | 40 | 41 | 42 |
43 | Accoutrement: Color 44 | 45 | 2.3.1 46 | 47 |
48 |
49 | 50 |
51 | 52 | 168 | 169 | 170 |
171 | 172 | 173 |
174 | 175 | 176 | 177 | 189 | 190 | 191 | 192 |
193 |

Accoutrement-Color

194 |

Sass color-palette management by OddBird

195 |
    196 |
  • Organize all your colors into a single map, or set of maps
  • 197 |
  • Document color relationships directly in the code
  • 198 |
  • Automate WCAG-appropriate contrast checking
  • 199 |
  • Generate color-palette documentation with Herman
  • 200 |
201 |

OddBird’s Accoutrement toolkits are designed around the idea 202 | that code should be meaningful to both humans and machines – 203 | opening the door for automation, 204 | while improving or maintaining readability. 205 | These tools integrate with Herman, 206 | our automated living pattern-library generator 207 | built on SassDoc.

208 |

Other Accoutrement include…

209 |
    210 |
  • Init 211 | provides lightweight browser-normalization.
  • 212 |
  • Scale 213 | helps manage scale patterns like font-sizes, margins, and gutters.
  • 214 |
  • Type 215 | provides webfont management tools, 216 | and other typography helpers.
  • 217 |
  • Layout 218 | provides layout utilities such as 219 | box-sizing, intrinsic ratios, z-index management, 220 | named media-queries, and a clearfix.
  • 221 |
222 |

Quick Start: Colors

223 |

Install the package with npm or yarn:

224 |
npm install accoutrement-color
225 | yarn add accoutrement-color
226 | 
227 |

Import the library:

228 |
@import '<path-to>/accoutrement-color/sass/color';
229 | 
230 |

Establish your color palette:

231 |
$colors: (
232 |   // set explicit colors
233 |   'brand-pink': hsl(330, 85%, 62%),
234 |   'brand-light': #ddf,
235 |   'brand-dark': #224,
236 | 
237 |   // reference existing colors
238 |   'background': 'brand-light',
239 |   'border': 'brand-dark',
240 | 
241 |   // make adjustments as needed, using color functions
242 |   'link': 'brand-pink' ('shade': 25%, 'desaturate': 15%),
243 | );
244 | 
245 |

Access your colors from anywhere:

246 |
.example {
247 |   border-color: color('border');
248 | }
249 | 
250 |

You can also define your colors in smaller maps, 251 | and then add them to the global $colors variable 252 | using the merge-color() function, 253 | or add-colors() mixin.

254 |
$brand: (
255 |   'brand-pink': hsl(330, 85%, 62%),
256 |   'brand-light': #ddf,
257 |   'brand-dark': #224,
258 | );
259 | 
260 | $patterns: (
261 |   'background': 'brand-light',
262 |   'border': 'brand-dark',
263 |   'link': 'brand-pink' ('shade': 25%),
264 | );
265 | 
266 | // merge everything into the main $colors map…
267 | @include add-colors($brand, $patterns);
268 | 
269 |

We’ll also help you calculate WCAG-appropriate color contrasts:

270 |
a:hover {
271 |   // set a background, and get well-contrasted text
272 |   @include contrasted('link');
273 | 
274 |   // or return a contrasting color for use anywhere…
275 |   border-color: contrast('background');
276 | }
277 | 
278 | 279 |
280 | 281 | 282 |
283 |
284 |
285 |
286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | -------------------------------------------------------------------------------- /docs/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Search Results | Accoutrement: Color Documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 30 | 31 |
32 |
33 | 34 | 40 | 41 | 42 |
43 | Accoutrement: Color 44 | 45 | 2.3.1 46 | 47 |
48 |
49 | 50 |
51 | 52 | 168 | 169 | 170 |
171 | 172 | 177 | 178 | 179 |
180 | 181 |
182 |
183 |
184 |
185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /docs/util.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Tint & Shade | Accoutrement: Color Documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 30 | 31 |
32 |
33 | 34 | 40 | 41 | 42 |
43 | Accoutrement: Color 44 | 45 | 2.3.1 46 | 47 |
48 |
49 | 50 |
51 | 52 | 168 | 169 | 170 |
171 | 172 | 177 | 178 | 179 |
180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 |
195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 |
204 |

Tint & Shade Utilities

205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 |
216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 |
255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 |
270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 |
281 |

282 | 283 | @function 284 | 285 | 286 | 287 | tint() 288 | 289 | 290 | 291 | 292 | 293 |

294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 |
308 |

Mix a color with white to get a lighter tint.

309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 |
320 | 321 | 322 |
323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 |
336 | 337 |

338 | Parameters & Return 339 | 340 |

341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 |
351 |

352 | 353 | 354 | $color: 355 | 356 | 357 | (String | list) 358 | 359 |

360 | 361 | 362 | 363 |
364 |

The name of a color in your palette, 365 | with optional adjustments in the form of (<function-name>: <args>).

366 | 367 |
368 | 369 |
370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 |
379 |

380 | 381 | 382 | $percentage: 383 | 384 | 385 | (Percentage) 386 | 387 |

388 | 389 | 390 | 391 |
392 |

The percentage of white to mix in. 393 | Higher percentages will result in a lighter tint.

394 | 395 |
396 | 397 |
398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 |
409 |

410 | 411 | 412 | @return 413 | 414 | 415 | (Color) 416 | 417 |

418 | 419 | 420 | 421 |
422 |

A calculated css-ready color-value based on your global color palette.

423 | 424 |
425 | 426 |
427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 |
438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 |
453 | 454 |

455 | Requires 456 | 457 |

458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 |
481 |

482 | @function 483 | 484 | color() 486 | 487 | 488 | 489 | 490 |

491 | 492 | 493 |
494 | 495 | 496 | 497 | 498 | 499 |
500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 |
518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 |
533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 |
544 |

545 | 546 | @function 547 | 548 | 549 | 550 | shade() 551 | 552 | 553 | 554 | 555 | 556 |

557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 |
571 |

Mix a color with black to get a darker shade.

572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 |
583 | 584 | 585 |
586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 |
599 | 600 |

601 | Parameters & Return 602 | 603 |

604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 |
614 |

615 | 616 | 617 | $color: 618 | 619 | 620 | (String | list) 621 | 622 |

623 | 624 | 625 | 626 |
627 |

The name of a color in your palette, 628 | with optional adjustments in the form of (<function-name>: <args>).

629 | 630 |
631 | 632 |
633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 |
642 |

643 | 644 | 645 | $percentage: 646 | 647 | 648 | (Percentage) 649 | 650 |

651 | 652 | 653 | 654 |
655 |

The percentage of black to mix in. 656 | Higher percentages will result in a darker shade.

657 | 658 |
659 | 660 |
661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 |
672 |

673 | 674 | 675 | @return 676 | 677 | 678 | (Color) 679 | 680 |

681 | 682 | 683 | 684 |
685 |

A calculated css-ready color-value based on your global color palette.

686 | 687 |
688 | 689 |
690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 |
701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 |
716 | 717 |

718 | Requires 719 | 720 |

721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 |
744 |

745 | @function 746 | 747 | color() 749 | 750 | 751 | 752 | 753 |

754 | 755 | 756 |
757 | 758 | 759 | 760 | 761 | 762 |
763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 |
781 | 782 | 783 | 784 |
785 |
786 |
787 |
788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | 'use strict'; 4 | 5 | var beeper = require('beeper'); 6 | var chalk = require('chalk'); 7 | var gulp = require('gulp'); 8 | var log = require('fancy-log'); 9 | var sassdoc = require('sassdoc'); 10 | var sasslint = require('gulp-sass-lint'); 11 | 12 | var paths = { 13 | TEST_DIR: 'test/', 14 | SASS_DIR: 'sass/', 15 | IGNORE: [ 16 | '!**/.#*', 17 | '!**/flycheck_*' 18 | ], 19 | init: function () { 20 | this.SASS = [ 21 | this.SASS_DIR + '**/*.scss' 22 | ].concat(this.IGNORE); 23 | this.ALL_SASS = [ 24 | this.SASS_DIR + '**/*.scss', 25 | this.TEST_DIR + '**/*.scss' 26 | ].concat(this.IGNORE); 27 | return this; 28 | } 29 | }.init(); 30 | 31 | var onError = function (err) { 32 | log.error(chalk.red(err.message)); 33 | beeper(); 34 | this.emit('end'); 35 | }; 36 | 37 | var sasslintTask = function (src, failOnError, shouldLog) { 38 | if (shouldLog) { 39 | log('Running', '\'' + chalk.cyan('sasslint ' + src) + '\'...'); 40 | } 41 | var stream = gulp.src(src) 42 | .pipe(sasslint()) 43 | .pipe(sasslint.format()) 44 | .pipe(sasslint.failOnError()); 45 | if (!failOnError) { 46 | stream.on('error', onError); 47 | } 48 | return stream; 49 | }; 50 | 51 | gulp.task('sasslint', function () { 52 | return sasslintTask(paths.ALL_SASS, true); 53 | }); 54 | 55 | gulp.task('sasslint-nofail', function () { 56 | return sasslintTask(paths.ALL_SASS); 57 | }); 58 | 59 | gulp.task('sassdoc', function () { 60 | return gulp.src(paths.SASS) 61 | .pipe(sassdoc()); 62 | }); 63 | 64 | gulp.task('watch', function (cb) { 65 | gulp.watch(paths.SASS, gulp.parallel('sassdoc')); 66 | 67 | // lint scss on changes 68 | gulp.watch(paths.ALL_SASS).on('all', function (event, filepath) { 69 | if (event === 'add' || event === 'change') { 70 | sasslintTask(filepath, false, true); 71 | } 72 | }); 73 | 74 | // lint all scss when rules change 75 | gulp.watch('**/.sass-lint.yml', gulp.parallel('sasslint-nofail')); 76 | 77 | cb(); 78 | }); 79 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "accoutrement-color", 3 | "title": "Accoutrement: Color", 4 | "version": "2.3.1", 5 | "description": "Sass color-palette management and utilities.", 6 | "homepage": "http://oddbird.net/accoutrement-color/", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/oddbird/accoutrement-color.git" 10 | }, 11 | "devDependencies": { 12 | "beeper": "^1.1.1", 13 | "chalk": "^2.3.2", 14 | "fancy-log": "^1.3.2", 15 | "gulp": "^4.0.0", 16 | "gulp-sass-lint": "^1.3.4", 17 | "mocha": "^5.0.5", 18 | "sass-true": "^3.1.0", 19 | "sassdoc": "^2.5.0", 20 | "sassdoc-theme-herman": "^2.1.0" 21 | }, 22 | "author": "Miriam Suzanne ", 23 | "license": "MIT", 24 | "keywords": [ 25 | "sass", 26 | "accoutrement", 27 | "toolkit", 28 | "color", 29 | "eyeglass-module" 30 | ], 31 | "eyeglass": { 32 | "sassDir": "sass", 33 | "exports": false, 34 | "name": "accoutrement-color", 35 | "needs": "^1.0.0" 36 | }, 37 | "scripts": { 38 | "test": "node_modules/.bin/mocha", 39 | "commit": "npm test; gulp sasslint; gulp sassdoc" 40 | }, 41 | "bugs": { 42 | "url": "https://github.com/oddbird/accoutrement-color/issues" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /sass/_api.scss: -------------------------------------------------------------------------------- 1 | /// # Accessing Colors 2 | /// @group colors 3 | 4 | 5 | // Color 6 | // ----- 7 | /// The primary function for 8 | /// accessing colors in your palette, 9 | /// or making adjustments on the fly. 10 | /// 11 | /// This is more than a wrapper for `map-get($colors, $x)`. 12 | /// It also handles internal color-references, recursion, 13 | /// and functional color-adjustments. 14 | /// It has access to the global `$colors` map by default, 15 | /// but you can also pass in arbitrary color-palette maps as well. 16 | /// 17 | /// @group colors 18 | /// 19 | /// @parameter {string | list} $color - 20 | /// The name of a color in your palette, 21 | /// or a color description in the 22 | /// [map configuration format](config.html). 23 | /// 24 | /// @parameter {map} $palette [$colors] - 25 | /// Optional map containing the source color-palette. 26 | /// Defaults to the global `$colors` map. 27 | /// 28 | /// @return {color} - 29 | /// A calculated css-ready color, 30 | /// based on your global color palette and adjustments. 31 | /// 32 | /// @example scss 33 | /// $colors: ( 34 | /// 'background': #eee, 35 | /// 'text': #222, 36 | /// ); 37 | /// 38 | /// html { 39 | /// background: color('background'); 40 | /// color: color('text'); 41 | /// } 42 | @function color( 43 | $color, 44 | $palette: $colors 45 | ) { 46 | // Parse arguments 47 | $color: map-get($palette, $color) or $color; 48 | $base: nth($color, 1); 49 | $adjust: if(length($color) > 1, nth($color, 2), ()); 50 | 51 | // Recursive check 52 | $color: if(map-has-key($palette, $base), color($base, $palette), $base); 53 | 54 | // Adjustments 55 | @each $function, $value in $adjust { 56 | $function: _ac-color-get-function($function); 57 | $color: call($function, $color, $value...); 58 | } 59 | 60 | @return $color; 61 | } 62 | -------------------------------------------------------------------------------- /sass/_color.scss: -------------------------------------------------------------------------------- 1 | // Color Toolkit 2 | // ============= 3 | 4 | 5 | @import 'pow'; 6 | @import 'utils'; 7 | @import 'contrast'; 8 | @import 'config'; 9 | @import 'api'; 10 | -------------------------------------------------------------------------------- /sass/_config.scss: -------------------------------------------------------------------------------- 1 | /// # Color Configuration 2 | /// @group a-config 3 | 4 | 5 | // Local Functions 6 | // --------------- 7 | /// These functions are defined internally, 8 | /// and can be called by name without first being captured 9 | /// using the Sass `get-function()` approach. 10 | /// 11 | /// Don't make changes to this map directly. 12 | /// You can add your own named functions in the `$functions` map. 13 | /// 14 | /// @access public 15 | /// @group a-config 16 | /// @see $functions 17 | /// 18 | /// @type map 19 | $_LOCAL-COLOR-FUNCTIONS: ( // sass-lint:disable-line variable-name-format 20 | 'tint', 21 | 'shade', 22 | 'contrast', 23 | ); 24 | 25 | 26 | // Functions 27 | // --------- 28 | /// Define any additional color functions required 29 | /// to generate relataionships in the `$colors` map. 30 | /// This is only necessary for newer versions of Sass, 31 | /// where functions are first-class, 32 | /// and can be captured using `get-function($name)`. 33 | /// 34 | /// ```scss 35 | /// $functions: ( 36 | /// 'darken': get-function('darken'), 37 | /// 'lighten': get-function('lighten'), 38 | /// ); 39 | /// ``` 40 | /// 41 | /// @group a-config 42 | /// @type map 43 | /// @see $_LOCAL-COLOR-FUNCTIONS 44 | $functions: () !default; 45 | 46 | 47 | // Color Map 48 | // --------- 49 | /// A variable storing the map of 50 | /// all colors globally-avialble on your project. 51 | /// Any colors added to the `$colors` map will be accesible 52 | /// to the `color()` function by default. 53 | /// 54 | /// Define each color with a `name`, `base-value`, 55 | /// and optional `adjustments`… 56 | /// 57 | /// ``` 58 | /// $colors: ( 59 | /// 'color-name': , 60 | /// 'color-two': ('': ''), 61 | /// // will return: function-name($base-value, $arguments...) 62 | /// ); 63 | /// ``` 64 | /// 65 | /// - Name your colors anything – from abstractions like `brand-pink`, 66 | /// to concrete patterns like `button` or `widget-background`. 67 | /// - Base-values can be CSS-ready colors (hex, rgb, hsla), 68 | /// or references other colors in the map. 69 | /// - Adjustments are a nested map of color functions and arguments, 70 | /// for adjusting colors directly in your palette. 71 | /// 72 | /// The color-names `contrast-light` and `contrast-dark` are special. 73 | /// Use those names to define the default light-and-dark options 74 | /// for our color-contrast tools. 75 | /// They default to `white` and `black` respectively. 76 | /// 77 | /// @group a-config 78 | /// @see {function} color 79 | /// @see {function} contrast 80 | /// 81 | /// @example scss - simple color definitions 82 | /// $colors: ( 83 | /// 'brand-pink': hsl(330, 85%, 62%), 84 | /// 'brand-light': #fff, 85 | /// 'brand-dark': #222, 86 | /// ); 87 | /// @example scss - reference other colors 88 | /// $colors: ( 89 | /// 'background': 'brand-light', 90 | /// 'text': 'brand-dark', 91 | /// 'link': 'brand-pink', 92 | /// ); 93 | /// @example scss - adjust referenced colors with any color function 94 | /// $colors: ( 95 | /// 'focus': 'link' ('darken': 15%, 'desaturate': 15%), 96 | /// ); 97 | $colors: () !default; 98 | 99 | 100 | // Add Colors 101 | // ---------- 102 | /// Merge individual color maps into the global `$colors` variable, 103 | /// in case you want to define colors in smaller groups 104 | /// such as `brand-colors`, `link-colors`, etc 105 | /// before merging them into a single global color-palette. 106 | /// This can be useful for internal organization, 107 | /// documentation with [SassDoc][SassDoc], 108 | /// or integration with our pattern-library generator: 109 | /// [Herman][Herman]. 110 | /// 111 | /// [SassDoc]: http://sassdoc.com/ 112 | /// [Herman]: http://oddbird.net/herman/ 113 | /// 114 | /// @group a-config 115 | /// 116 | /// @parameter {map...} $maps - 117 | /// Pass any number of maps to be merged. 118 | /// @output - 119 | /// An updated global `$colors` variable, 120 | /// with new maps merged in. 121 | /// 122 | /// @example scss 123 | /// $brand-colors: ( 124 | /// 'brand-dark': #222, 125 | /// 'brand-pink': hsl(330, 85%, 62%), 126 | /// ); 127 | /// 128 | /// $text-colors: ( 129 | /// 'text': 'brand-dark', 130 | /// 'link': 'brand-pink', 131 | /// ); 132 | /// 133 | /// @include add-colors($brand-colors, $text-colors); 134 | @mixin add-colors ( 135 | $maps... 136 | ) { 137 | $colors: merge-colors($colors, $maps...) !global; 138 | } 139 | 140 | 141 | 142 | // Merge Colors 143 | // ------------ 144 | /// Merge multiple color maps into a single map, 145 | /// in case you want to define colors in smaller groups – 146 | /// such as `brand-colors`, `link-colors`, etc. – 147 | /// before merging them into a single map. 148 | /// 149 | /// This is like `add-colors`, 150 | /// but returns the combined map 151 | /// without assigning it to the `$colors` variable. 152 | /// 153 | /// @group a-config 154 | /// 155 | /// @parameter {maps...} $maps - 156 | /// Pass any number of maps to be merged. 157 | /// @return {map} - 158 | /// The merged map of colors. 159 | /// @example scss 160 | /// $brand-colors: ( 161 | /// 'brand-dark': #222, 162 | /// 'brand-pink': hsl(330, 85%, 62%), 163 | /// ); 164 | /// 165 | /// $text-colors: ( 166 | /// 'text': 'brand-dark', 167 | /// 'link': 'brand-pink', 168 | /// ); 169 | /// 170 | /// $colors: merge-colors($brand-colors, $text-colors); 171 | @function merge-colors( 172 | $maps... 173 | ) { 174 | $return: (); 175 | 176 | @each $map in $maps { 177 | $return: map-merge($return, $map); 178 | } 179 | 180 | @return $return; 181 | } 182 | -------------------------------------------------------------------------------- /sass/_contrast.scss: -------------------------------------------------------------------------------- 1 | /// # Managing Contrast & Accessibility 2 | /// @group contrast 3 | 4 | 5 | // WCAG Contrast 6 | // ------------- 7 | /// These named contrast-ratios are defined by the [WCAG][WCAG]. 8 | /// 9 | /// [WCAG]: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast 10 | /// 11 | /// @access private 12 | $WCAG-CONTRAST: ( // sass-lint:disable-line variable-name-format 13 | 'AA-large': 3, 14 | 'AA': 4.5, 15 | 'AAA': 7, 16 | ); 17 | 18 | 19 | // Contrast 20 | // -------- 21 | /// For any color, select the best contrast among a set of options. 22 | /// For best results, pass in a combination of light and dark colors 23 | /// to contrast against –  24 | /// or define default `contrast-light` and `contrast-dark` values 25 | /// in your global `$colors` map. 26 | /// 27 | /// @group contrast 28 | /// 29 | /// @param {string | list} $color - 30 | /// The name or value of a color. 31 | /// @param {arglist} $options [#000, #fff] - 32 | /// Two or more colors to contrast against. 33 | /// This function will choose the best contrast of all the options provided, 34 | /// or the `contrast-light` and `contrast-dark` defaults 35 | /// if they are defined in your color palette, 36 | /// otherwise `white` and `black` are the default options. 37 | /// @return {color} - 38 | /// Whichever color-option has the highest contrast-ratio to `$color`. 39 | /// 40 | /// @example scss - default options 41 | /// $background: #333; 42 | /// html { 43 | /// background: $background; 44 | /// color: contrast($background); 45 | /// } 46 | /// @example scss - explicit options 47 | /// $background: #333; 48 | /// html { 49 | /// background: $background; 50 | /// color: contrast($background, red, orange, yellow, green, blue, indigo); 51 | /// } 52 | @function contrast( 53 | $color, 54 | $options... 55 | ) { 56 | // Establish default options if they are missing 57 | @if length($options) == 0 { 58 | $options: append($options, map-get($colors, 'contrast-light') or #fff); 59 | $options: append($options, map-get($colors, 'contrast-dark') or #000); 60 | } @else if length($options) == 1 { 61 | @error 'Provide at least two contrasting color options for `contrast()`'; 62 | } 63 | 64 | // Get the colors and their contrasts 65 | $color-val: color($color); 66 | $color-lum: luminance($color-val); 67 | $color-list: (); 68 | $contrast-list: (); 69 | 70 | @each $item in $options { 71 | $item: color($item); 72 | $luminance: luminance($item); 73 | $contrast: contrast-ratio($color-lum, $luminance); 74 | 75 | $color-list: append($color-list, $item); 76 | $contrast-list: append($contrast-list, $contrast); 77 | } 78 | 79 | // Find the best results 80 | $best-ratio: max($contrast-list...); 81 | $best-color: nth($color-list, index($contrast-list, $best-ratio)); 82 | 83 | @return $best-color; 84 | } 85 | 86 | 87 | // Contrasted 88 | // ---------- 89 | /// Apply any background color, 90 | /// along with the highest-contraast text color from a set of options. 91 | /// This works the same as the `contrast` function, 92 | /// but applies the resulting values to `background-color` 93 | /// and text `color` properties. 94 | /// 95 | /// @group contrast 96 | /// 97 | /// @param {string | list} $background - 98 | /// The name or value of your desired background color. 99 | /// @param {arglist} $options [#fff, #000] - 100 | /// A list of colors to contrast against, 101 | /// defaulting to `white` and `black` 102 | /// or your `contrast-light` and `contrast-dark` settings 103 | /// if they are prodided in the global `$colors` map. 104 | /// @output - 105 | /// Sets the `background-color` to `$background` 106 | /// and the foreground `color` to 107 | /// whichever option has better contrast against the given background. 108 | /// 109 | /// @example scss - default options 110 | /// $background: #333; 111 | /// html { 112 | /// @include contrasted($background); 113 | /// } 114 | /// @example scss - explicit options 115 | /// $background: #333; 116 | /// html { 117 | /// @include contrasted($background, red, orange, yellow, green, blue, indigo); 118 | /// } 119 | @mixin contrasted( 120 | $background, 121 | $options... 122 | ) { 123 | $background: color($background); 124 | 125 | background-color: $background; 126 | color: contrast($background, $options...); 127 | } 128 | 129 | 130 | // Contrast Ratio 131 | // -------------- 132 | /// Compare two colors using the WCAG comparison algorythm, 133 | /// and return the resulting contrast-ratio. 134 | /// Optionally pass in a standard (AA, AAA, AA-large) 135 | /// and return `false` when the contrast-check fails. 136 | /// 137 | /// - 'AA-large' == `3:1` 138 | /// - 'AA' == `4.5:1` 139 | /// - 'AAA' == `7:1` 140 | /// 141 | /// @group contrast 142 | /// @link http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef WCAG Contrast Definition 143 | /// 144 | /// @param {string | list | number} $color - 145 | /// The name of a color in your palette, 146 | /// any other color value, 147 | /// or even a pre-calculated numeric luminance. 148 | /// @param {string | list | number} $contrast - 149 | /// The name or value of a color to contrast against the first. 150 | /// @param {'AA' | 'AA-large' | 'AAA' | number | false} $require [false] - 151 | /// An optional WCAG contrast ratio to require. 152 | /// The function will return `false` if the required ratio is not met. 153 | /// @return {number} - 154 | /// The WCAG-defined contrast-ratio of two colors. 155 | /// 156 | /// @example scss 157 | /// /* black and white: #{contrast-ratio(white, black)} */ 158 | /// /* failed 'AAA': #{contrast-ratio(white, #999, 'AAA')} */ 159 | @function contrast-ratio( 160 | $base, 161 | $contrast, 162 | $require: false 163 | ) { 164 | $is-lumins: (type-of($base) == 'number'); 165 | $uppercase: ( 166 | 'aaa': 'AAA', 167 | 'aa': 'AA', 168 | 'aa-large': 'AA-large' 169 | ); 170 | 171 | $base-lumin: if($is-lumins, $base, luminance($base)); 172 | $contrast-lumin: if($is-lumins, $contrast, luminance($contrast)); 173 | 174 | $darker: min($base-lumin, $contrast-lumin); 175 | $lighter: max($base-lumin, $contrast-lumin); 176 | 177 | $ratio: ($lighter + 0.05) / ($darker + 0.05); 178 | 179 | @if (type-of($require) != 'number') { 180 | $require: map-get($uppercase, $require) or $require; 181 | $require: map-get($WCAG-CONTRAST, $require); // sass-lint:disable-line variable-name-format 182 | } 183 | 184 | @if $require and ($ratio < $require) { 185 | @return false; 186 | } 187 | 188 | @return $ratio; 189 | } 190 | 191 | 192 | // Luminance 193 | // --------- 194 | /// Get the WCAG luminance of a color in your palette. 195 | /// 196 | /// @group contrast 197 | /// @link http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef WCAG Relative Luminance 198 | /// 199 | /// @param {string | list} $color - 200 | /// The name or value of a color. 201 | /// @return {number} - 202 | /// WCAG-defined numeric luminance value. 203 | @function luminance( 204 | $color 205 | ) { 206 | $color: color($color); 207 | $luminance: 0; 208 | 209 | @if (type-of($color) != 'color') { 210 | @error '`#{$color}` is not a color.'; 211 | } 212 | 213 | @each $component in 'red' 'green' 'blue' { 214 | $function: $component; 215 | 216 | @if function-exists('get-function') { 217 | $function: get-function($component); 218 | } 219 | 220 | $value: call($function, $color) / 255; 221 | 222 | @if ($value < 0.03928) { 223 | $value: $value / 12.92; 224 | } @else { 225 | $base: ($value + 0.055) / 1.055; 226 | $value: _acc-pow($base, 2.4); 227 | } 228 | 229 | @if ($component == 'red') { 230 | $value: $value * 0.2126; 231 | } @else if ($component == 'green') { 232 | $value: $value * 0.7152; 233 | } @else { 234 | $value: $value * 0.0722; 235 | } 236 | 237 | $luminance: $luminance + $value; 238 | } 239 | 240 | @return $luminance; 241 | } 242 | -------------------------------------------------------------------------------- /sass/_pow.scss: -------------------------------------------------------------------------------- 1 | /// # MathSass Functions 2 | /// 3 | /// *We borrowed this set of math constants and functions 4 | /// from Takeru Suzuki's wonderful [MathSass][MathSass] library. 5 | /// See the full MIT License below…* 6 | /// 7 | /// [MathSass]: https://github.com/terkel/mathsass/ 8 | /// @access private 9 | 10 | 11 | // Constants 12 | // --------- 13 | $_LN2: 0.6931471805599453; // sass-lint:disable-line variable-name-format 14 | $_SQRT2: 1.4142135623730951; // sass-lint:disable-line variable-name-format 15 | 16 | 17 | /// Returns base to the exponent power. 18 | /// 19 | /// @access private 20 | /// 21 | /// @param {Number} $base – 22 | /// The base number 23 | /// @param {Number} $exp - 24 | /// The exponent to which to raise base 25 | /// @return {Number} 26 | /// @example scss 27 | /// /* #{ _acc-pow(4, 2) } */ 28 | /// /* #{ _acc-pow(4, -2) } */ 29 | /// /* #{ _acc-pow(4, 0.2) } */ 30 | @function _acc-pow( 31 | $base, 32 | $exp 33 | ) { 34 | @if $exp == floor($exp) { 35 | $r: 1; 36 | $s: 0; 37 | @if $exp < 0 { 38 | $exp: $exp * -1; 39 | $s: 1; 40 | } 41 | @while $exp > 0 { 42 | @if $exp % 2 == 1 { 43 | $r: $r * $base; 44 | } 45 | $exp: floor($exp * 0.5); 46 | $base: $base * $base; 47 | } 48 | @return if($s != 0, 1 / $r, $r); 49 | } @else if $base == 0 and $exp > 0 { 50 | @return 0; 51 | } @else { 52 | $expint: floor($exp); 53 | $r1: _acc-pow($base, $expint); 54 | $r2: _exp(_acc-log($base) * ($exp - $expint)); 55 | @return $r1 * $r2; 56 | } 57 | } 58 | 59 | 60 | /// A good approximation for $x close to 0. 61 | /// @access private 62 | @function _exp( 63 | $x 64 | ) { 65 | $ret: 0; 66 | $i: 1; 67 | @for $n from 0 to 24 { 68 | $ret: $ret + $i; 69 | $i: $i * $x / ($n + 1); 70 | } 71 | @return $ret; 72 | } 73 | 74 | 75 | /// Returns the natural logarithm of a number. 76 | /// 77 | /// @access private 78 | /// 79 | /// @param {Number} $x 80 | /// @param {Number} $b The base number 81 | /// @example scss 82 | /// /* #{ _acc-log(2) } */ 83 | /// /* #{ _acc-log(10) } */ 84 | /// /* #{ _acc-log(2, 10) } */ 85 | @function _acc-log( 86 | $x, 87 | $b: null 88 | ) { 89 | @if $b != null { 90 | @return _acc-log($x) / _acc-log($b); 91 | } 92 | 93 | @if $x <= 0 { 94 | @return 0 / 0; 95 | } 96 | $k: nth(_acc-frexp($x / $_SQRT2), 2); // sass-lint:disable-line variable-name-format 97 | $x: $x / _acc-ldexp(1, $k); 98 | 99 | @return $_LN2 * $k + _acc-log-approx($x); // sass-lint:disable-line variable-name-format 100 | } 101 | 102 | 103 | /// a good aproximation for $x close to 1 104 | /// @access private 105 | @function _acc-log-approx( 106 | $x 107 | ) { 108 | $x: ($x - 1) / ($x + 1); 109 | $x2: $x * $x; 110 | $i: 1; 111 | $s: $x; 112 | $sp: null; 113 | @while $sp != $s { 114 | $x: $x * $x2; 115 | $i: $i + 2; 116 | $sp: $s; 117 | $s: $s + $x / $i; 118 | } 119 | @return 2 * $s; 120 | } 121 | 122 | 123 | /// Returns a two-element list 124 | /// containing the normalized fraction and exponent of number. 125 | /// 126 | /// @access private 127 | /// 128 | /// @param {Number} $x 129 | /// @return {List} fraction, exponent 130 | @function _acc-frexp( 131 | $x 132 | ) { 133 | $exp: 0; 134 | @if $x < 0 { 135 | $x: $x * -1; 136 | } 137 | @if $x < 0.5 { 138 | @while $x < 0.5 { 139 | $x: $x * 2; 140 | $exp: $exp - 1; 141 | } 142 | } @else if $x >= 1 { 143 | @while $x >= 1 { 144 | $x: $x / 2; 145 | $exp: $exp + 1; 146 | } 147 | } 148 | @return $x, $exp; 149 | } 150 | 151 | 152 | // Returns $x * 2^$exp 153 | /// 154 | /// @access private 155 | /// 156 | /// @param {Number} $x 157 | /// @param {Number} $exp 158 | @function _acc-ldexp( 159 | $x, 160 | $exp 161 | ) { 162 | $b: if($exp >= 0, 2, 1 / 2); 163 | @if $exp < 0 { 164 | $exp: $exp * -1; 165 | } 166 | @while $exp > 0 { 167 | @if $exp % 2 == 1 { 168 | $x: $x * $b; 169 | } 170 | $b: $b * $b; 171 | $exp: floor($exp * 0.5); 172 | } 173 | @return $x; 174 | } 175 | 176 | 177 | /// ## [Copyright (C) 2013 Takeru Suzuki][MathSass] 178 | /// 179 | /// Permission is hereby granted, free of charge, 180 | /// to any person obtaining a copy of this software 181 | /// and associated documentation files (the "Software"), 182 | /// to deal in the Software without restriction, 183 | /// including without limitation the rights to use, 184 | /// copy, modify, merge, publish, distribute, sublicense, 185 | /// and/or sell copies of the Software, 186 | /// and to permit persons to whom the Software is furnished to do so, 187 | /// subject to the following conditions: 188 | /// 189 | /// The above copyright notice and this permission notice 190 | /// shall be included in all copies or substantial portions of the Software. 191 | /// 192 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 193 | /// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 194 | /// THE WARRANTIES OF MERCHANTABILITY, 195 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 196 | /// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 197 | /// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 198 | /// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 199 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE 200 | /// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 201 | /// 202 | /// [MathSass]: https://github.com/terkel/mathsass/ 203 | /// @access private 204 | -------------------------------------------------------------------------------- /sass/_utils.scss: -------------------------------------------------------------------------------- 1 | /// # Tint & Shade Utilities 2 | /// @group util 3 | 4 | 5 | // Tint 6 | // ---- 7 | /// Mix a color with `white` to get a lighter tint. 8 | /// 9 | /// @group util 10 | /// 11 | /// @param {String | list} $color - 12 | /// The name of a color in your palette, 13 | /// with optional adjustments in the form of `(: )`. 14 | /// @param {Percentage} $percentage - 15 | /// The percentage of white to mix in. 16 | /// Higher percentages will result in a lighter tint. 17 | /// @return {Color} - 18 | /// A calculated css-ready color-value based on your global color palette. 19 | @function tint( 20 | $color, 21 | $percentage 22 | ) { 23 | $color: color($color); 24 | 25 | @return mix(#fff, $color, $percentage); 26 | } 27 | 28 | 29 | // Shade 30 | // ----- 31 | /// Mix a color with `black` to get a darker shade. 32 | /// 33 | /// @group util 34 | /// 35 | /// @param {String | list} $color - 36 | /// The name of a color in your palette, 37 | /// with optional adjustments in the form of `(: )`. 38 | /// @param {Percentage} $percentage - 39 | /// The percentage of black to mix in. 40 | /// Higher percentages will result in a darker shade. 41 | /// @return {Color} - 42 | /// A calculated css-ready color-value based on your global color palette. 43 | @function shade( 44 | $color, 45 | $percentage 46 | ) { 47 | $color: color($color); 48 | 49 | @return mix(#000, $color, $percentage); 50 | } 51 | 52 | 53 | // Get Function 54 | // ------------ 55 | /// Get a first-class function in Sass 3.5+, 56 | /// or the function name string (unchanged) 57 | /// in older Sass versions. 58 | /// This is safe to use internally, 59 | /// as it allows users to pass in 60 | /// either a string, or a previously-captured function. 61 | /// 62 | /// @access private 63 | /// 64 | /// @param {String | Function} $function - 65 | /// The name (string) of a function, 66 | /// or the function to be called. 67 | /// @return {String | Function} - 68 | /// Returns a first-class function in Sass 3.5+, 69 | /// or the function name string in older Sass versions. 70 | @function _ac-color-get-function( 71 | $function 72 | ) { 73 | $type: type-of($function); 74 | 75 | @if ($type == 'function') { 76 | @return $function; 77 | } 78 | 79 | @if function-exists('get-function') { 80 | // sass-lint:disable variable-name-format 81 | @if index($_LOCAL-COLOR-FUNCTIONS, $function) { 82 | @return get-function($function); 83 | } 84 | 85 | @if map-has-key($functions, $function) { 86 | $function: map-get($functions, $function); 87 | @return _ac-color-get-function($function); 88 | } 89 | 90 | @error '[#{$type}] `#{$function}` must be a first-class function'; 91 | } 92 | 93 | @return $function; 94 | } 95 | -------------------------------------------------------------------------------- /test/scss/_api.scss: -------------------------------------------------------------------------------- 1 | // Color API Tests 2 | // =============== 3 | 4 | 5 | // Color [function] 6 | // ---------------- 7 | @include describe('Color [function]') { 8 | @include it('Named color') { 9 | @include assert-equal( 10 | color('simple'), 11 | map-get($colors, 'simple'), 12 | 'Returns simple color based on styleguide keyword' 13 | ); 14 | } 15 | 16 | @include it('Referenced color') { 17 | @include assert-equal( 18 | color('primary'), 19 | map-get($colors, 'red'), 20 | 'Returns color based on referential styleguide keyword' 21 | ); 22 | } 23 | 24 | @include it('Adjusted color') { 25 | @include assert-equal( 26 | color('secondary'), 27 | desaturate(tint(map-get($colors, 'red'), 30%), 25%), 28 | 'Returns color based on self-referential keyword and adjustments' 29 | ); 30 | } 31 | 32 | @include it('Complex nesting of colors') { 33 | @include assert-equal( 34 | color('wtf'), 35 | adjust-hue(desaturate(tint(map-get($colors, 'red'), 30%), 25%), 24deg), 36 | 'Returns color based on multiple keywords and adjustments' 37 | ); 38 | } 39 | 40 | @include it('Multiple adjustment function arguments') { 41 | $adjust: ( 42 | 'contrast': (#999, #666, #333), 43 | ); 44 | @include assert-equal( 45 | color(#fcc $adjust), 46 | #333, 47 | 'Handles multiple arguments to color-adjustment function' 48 | ); 49 | } 50 | 51 | @include it('Works with a custom palette') { 52 | $my-palette: ( 53 | 'my-base': #393, 54 | 'my-adjustment': 'my-base' ('shade': 10%), 55 | ); 56 | 57 | $expect: map-get($my-palette, 'my-base'); 58 | $expect: shade($expect, 10%); 59 | 60 | @include assert-equal( 61 | color('my-adjustment', $my-palette), 62 | $expect 63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /test/scss/_config.scss: -------------------------------------------------------------------------------- 1 | // Color Config Tests 2 | // ================== 3 | 4 | 5 | // Merge Colors [function] 6 | // ----------------------- 7 | @include describe('Merge Colors [function]') { 8 | $a: ('red': #f33); 9 | $b: ('green': #3f3); 10 | 11 | @include it('Merges colors into a single map') { 12 | @include assert-equal( 13 | merge-colors($a, $b), 14 | map-merge($a, $b) 15 | ); 16 | } 17 | } 18 | 19 | 20 | // Add Colors [mixin] 21 | // ------------------ 22 | @include describe('Add Colors [mixin]') { 23 | $old: $colors; 24 | $a: ('red': #f33); 25 | $b: ('green': #3f3); 26 | 27 | @include add-colors($a, $b); 28 | 29 | @include it('Merges colors, and updates global variable') { 30 | @include assert-equal( 31 | $colors, 32 | map-merge($colors, map-merge($a, $b)) 33 | ); 34 | } 35 | 36 | $colors: $old !global; 37 | } 38 | -------------------------------------------------------------------------------- /test/scss/_contrast.scss: -------------------------------------------------------------------------------- 1 | // Contrast Tests 2 | // ============== 3 | 4 | 5 | // Luminance [function] 6 | // -------------------- 7 | @include describe('Luminance [function]') { 8 | @include it('Returns proper luminance of a color') { 9 | @include assert-equal( 10 | luminance(#fff), 11 | 1, 12 | 'white', 13 | $inspect: true 14 | ); 15 | 16 | @include assert-equal( 17 | luminance(#000), 18 | 0, 19 | 'black', 20 | $inspect: true 21 | ); 22 | 23 | @include assert-equal( 24 | luminance(#ff0), 25 | 0.9278, 26 | 'yellow', 27 | $inspect: true 28 | ); 29 | 30 | @include assert-equal( 31 | luminance(#0f0), 32 | 0.7152, 33 | 'green', 34 | $inspect: true 35 | ); 36 | 37 | @include assert-equal( 38 | luminance(#3492a1), 39 | 0.23861, 40 | 'blue', 41 | $inspect: true 42 | ); 43 | } 44 | } 45 | 46 | 47 | // Contrast Ratio [function] 48 | // ------------------------- 49 | @include describe('Contrast Ratio [function]') { 50 | @include it('Returns contrast ratio between two colors') { 51 | @include assert-equal( 52 | contrast-ratio(#fff, #fff), 53 | 1 54 | ); 55 | 56 | @include assert-equal( 57 | contrast-ratio(#000, #fff), 58 | 21 59 | ); 60 | } 61 | 62 | @include it('Returns contrast ratio if test is met') { 63 | @include assert-equal( 64 | contrast-ratio(#333, #999, 'aa-large'), 65 | 4.43472, 66 | $inspect: true 67 | ); 68 | } 69 | 70 | @include it('Returns false if test is not met') { 71 | @include assert-equal( 72 | contrast-ratio(#333, #999, 'AAA'), 73 | false 74 | ); 75 | } 76 | } 77 | 78 | 79 | // Contrast [function] 80 | // ------------------- 81 | @include describe('Contrast [function]') { 82 | @include it('Dark on light') { 83 | @include assert-equal( 84 | contrast(#eee), 85 | color('contrast-dark'), 86 | 'Returns a dark color to contrast a light one.' 87 | ); 88 | } 89 | 90 | @include it('Light on dark') { 91 | @include assert-equal( 92 | contrast('dark'), 93 | color('contrast-light'), 94 | 'Returns a light color to contrast a dark one.' 95 | ); 96 | } 97 | 98 | $original-colors: $colors; 99 | $colors: () !global; 100 | 101 | @include it('Default light fallback') { 102 | @include assert-equal( 103 | contrast(#000), 104 | #fff, 105 | 'Returns white for light contrast when none is given.' 106 | ); 107 | } 108 | 109 | @include it('Default dark fallback') { 110 | @include assert-equal( 111 | contrast(#fff), 112 | #000, 113 | 'Returns black for dark contrast when none is given.' 114 | ); 115 | } 116 | 117 | $colors: $original-colors !global; 118 | 119 | @include it('Multiple contrast options') { 120 | @include assert-equal( 121 | contrast('primary', #ff0, #fcc, #0f0, 'light', #003), 122 | #003, 123 | 'Returns the best option from the list.' 124 | ); 125 | } 126 | } 127 | 128 | 129 | // Contrasted [mixin] 130 | // ------------------ 131 | @include describe('contrasted [mixin]') { 132 | @include it('Dark on light') { 133 | @include assert('Use a dark color on a light background.') { 134 | @include output { 135 | @include contrasted(#eee); 136 | } 137 | 138 | @include expect { 139 | background-color: #eee; 140 | color: color('contrast-dark'); 141 | } 142 | } 143 | } 144 | 145 | @include it('Light on dark') { 146 | @include assert('Use a light color on a dark background.') { 147 | @include output { 148 | @include contrasted('dark'); 149 | } 150 | 151 | @include expect { 152 | background-color: color('dark'); 153 | color: color('contrast-light'); 154 | } 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /test/scss/_pow.scss: -------------------------------------------------------------------------------- 1 | // MathSass Tests 2 | // ============== 3 | 4 | @include describe('Pow [function]') { 5 | @include it('should calculate exponents') { 6 | @include assert-equal( 7 | _acc-pow(4, 2), 8 | 16 9 | ); 10 | } 11 | 12 | @include it('should handle zero correctly') { 13 | @include assert-equal( 14 | _acc-pow(0, 0), 15 | 1 16 | ); 17 | @include assert-equal( 18 | _acc-pow(3.5, 0), 19 | 1 20 | ); 21 | @include assert-equal( 22 | _acc-pow(0, 3.5), 23 | 0 24 | ); 25 | } 26 | 27 | @include it('should calculate negative exponents') { 28 | @include assert-equal( 29 | _acc-pow(4, -2), 30 | 0.0625 31 | ); 32 | } 33 | 34 | @include it('should calculate decimal exponents') { 35 | @include assert-equal( 36 | _acc-pow(4, 0.2), 37 | 1.31951, 38 | $inspect: true 39 | ); 40 | } 41 | } 42 | 43 | 44 | @include describe('Log [function]') { 45 | @include it('should calculate the natural logarithm of a number') { 46 | @include assert-equal( 47 | _acc-log(2), 48 | 0.69315, 49 | $inspect: true 50 | ); 51 | @include assert-equal( 52 | _acc-log(10), 53 | 2.30259, 54 | $inspect: true 55 | ); 56 | @include assert-equal( 57 | _acc-log(2, 10), 58 | 0.30103, 59 | $inspect: true 60 | ); 61 | } 62 | 63 | @include it('should calculate the natural logarithm of a large fractional number') { 64 | @include assert-equal( 65 | _acc-log(12345.678), 66 | 9.421061, 67 | $inspect: true 68 | ); 69 | } 70 | 71 | @include it('should calculate the natural logarithm of a small fractional number') { 72 | @include assert-equal( 73 | _acc-log(0.0001), 74 | -9.21034, 75 | $inspect: true 76 | ); 77 | } 78 | } 79 | 80 | 81 | @include describe('Frexp [function]') { 82 | @include it('should return two item list containing the normalized fraction and exponent of number') { 83 | @include assert-equal( 84 | _acc-frexp(2), 85 | (0.5, 2) 86 | ); 87 | @include assert-equal( 88 | _acc-frexp(5), 89 | (0.625, 3) 90 | ); 91 | } 92 | } 93 | 94 | 95 | @include describe('Ldxp [function]') { 96 | @include it('should calculate ldexp') { 97 | @include assert-equal( 98 | _acc-ldexp(2, 1), 99 | 4 100 | ); 101 | @include assert-equal( 102 | _acc-ldexp(5, 2), 103 | 20x 104 | ); 105 | } 106 | 107 | @include it('should calculate ldexp with negative exp') { 108 | @include assert-equal( 109 | _acc-ldexp(2, -1), 110 | 1 111 | ); 112 | @include assert-equal( 113 | _acc-ldexp(5, -2), 114 | 1.25 115 | ); 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /test/scss/_utils.scss: -------------------------------------------------------------------------------- 1 | // Color Utility Tests 2 | // =================== 3 | 4 | 5 | // Tint [function] 6 | // --------------- 7 | @include describe('Tint [function]') { 8 | @include it('Adjusts the tint of a color') { 9 | @include assert-equal( 10 | tint('primary', 25%), 11 | mix(#fff, color('primary'), 25%), 12 | 'Returns a color mixed with white at a given weight.' 13 | ); 14 | } 15 | } 16 | 17 | 18 | // Shade [function] 19 | // ---------------- 20 | @include describe('Shade [function]') { 21 | @include it('Adjusts the shade of a color') { 22 | @include assert-equal( 23 | shade('primary', 25%), 24 | mix(#000, color('primary'), 25%), 25 | 'Returns a color mixed with black at a given weight.' 26 | ); 27 | } 28 | } 29 | 30 | 31 | // Get Function [function] 32 | // ----------------------- 33 | @include describe('Get Function [function]') { 34 | $test: _ac-color-get-function('tint'); 35 | $expect: 'tint'; 36 | 37 | @if function-exists('get-function') { 38 | $expect: get-function('tint'); 39 | 40 | @include it('Functions are returned without change') { 41 | @include assert-equal( 42 | _ac-color-get-function($expect), 43 | $expect 44 | ); 45 | } 46 | } 47 | 48 | @include it('Returns a function or function-name') { 49 | @include assert-equal($test, $expect); 50 | } 51 | 52 | @include it('Returned function or name is callable') { 53 | @include assert-equal( 54 | call($test, 'blue', 100%), 55 | white 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /test/scss/test.scss: -------------------------------------------------------------------------------- 1 | // Arrow Tests 2 | // =========== 3 | 4 | @import '../../node_modules/sass-true/sass/true'; 5 | @import '../../sass/color'; 6 | 7 | @if function-exists('get-function') { 8 | $functions: ( 9 | 'desaturate': get-function('desaturate'), 10 | 'rgba': get-function('rgba'), 11 | 'adjust-hue': get-function('adjust-hue'), 12 | ) !global; 13 | } 14 | 15 | $colors: ( 16 | 'blue': hsl(195, 85%, 62%), 17 | 'orange': hsl(24, 100%, 62%), 18 | 'red': hsl(0, 85%, 62%), 19 | 20 | 'simple': #969, 21 | 'primary': 'red', 22 | 'secondary': 'primary' ('tint': 30%, 'desaturate': 25%), 23 | 'alpha': 'simple' ('rgba': 0.5), 24 | 'wtf': 'secondary' ('adjust-hue': 24deg), 25 | 'hello': 'simple', 26 | 27 | 'dark': #111, 28 | 'light': #eee, 29 | 30 | 'contrast-dark': 'dark', 31 | 'contrast-light': 'light', 32 | ); 33 | 34 | 35 | @import 'pow'; 36 | @import 'utils'; 37 | @import 'contrast'; 38 | @import 'config'; 39 | @import 'api'; 40 | 41 | 42 | @include report; 43 | -------------------------------------------------------------------------------- /test/test_sass.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var sassTrue = require('sass-true'); 3 | 4 | var sassFile = path.join(__dirname, 'scss', 'test.scss'); 5 | sassTrue.runSass({file: sassFile}, describe, it); 6 | --------------------------------------------------------------------------------