Last active
August 29, 2015 14:13
-
-
Save tommycoppers/f761a41296eda2a8577c to your computer and use it in GitHub Desktop.
Map Functions - To add support to native List and Map functions in Sass
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ======================================== | |
// ===== Collections (Maps and Lists) ===== | |
// ======================================== | |
// ------------------------------------------------ | |
// Create and return a new list between a start and end point within provided list | |
// | |
// @param {List} $list - List to slice | |
// @param {Num} $start - Index to start the slice at | |
// @param {Num} $end - Index to end slice at | |
// | |
// @requires _slice-tests() | |
@function slice($list, $start: 1, $end: length($list)) { | |
$errors: _slice-tests($list, $start, $end); | |
@if not $errors { | |
$result: (); | |
@for $i from $start through $end { | |
$result: append($result, nth($list, $i), comma); | |
} | |
@return $result; | |
} | |
@else { | |
@return $list; | |
} | |
} | |
@function _slice-tests ($list, $start, $end) { | |
$errors: false; | |
@if type-of($start) != number or type-of($end) != number { | |
@warn "Either $start or $end are not a number for `slice`."; | |
$errors: true; | |
} | |
@else if $start > $end { | |
@warn "The start index has to be lesser than or equals to the end index for `slice`."; | |
$errors: true; | |
} | |
@else if $start < 1 or $end < 1 { | |
@warn "List indexes must be non-zero integers for `slice`."; | |
$errors: true; | |
} | |
@else if $start > length($list) { | |
@warn "List index is #{$start} but list is only #{length($list)} item long for `slice`."; | |
$errors: true; | |
} | |
@else if $end > length($list) { | |
@warn "List index is #{$end} but list is only #{length($list)} item long for `slice`."; | |
$errors: true; | |
} | |
@return $errors; | |
} | |
// ------------------------------------------------ | |
// Shorthand for map-get() which allows for nested value lookup and error handling | |
// | |
// @param {Map} $map - Map to parse | |
// @param {Argslist} $map-chain... - Path to the key (property) of the desired value | |
// | |
// @requires _get-initialize-test() | |
// @requires _get-map-keys-test() | |
@function get ($map, $map-chain...) { | |
$initialize-errors: _get-initialize-test($map, $map-chain); | |
$map-key-errors: false !default; | |
@if not $initialize-errors { | |
$key: nth($map-chain, 1); | |
$map-key-errors: _get-map-keys-test($map, $key); | |
@if not $map-key-errors { | |
$result: map-get($map, $key); | |
@if length($map-chain) > 1 { | |
$remainder: slice($map-chain, $start: 2); | |
@return get($result, $remainder...); | |
} | |
@return $result; | |
} | |
@return $map-chain; // Return if $map-key-errors == true | |
} | |
@return $map-chain; // Return if $initialize-errors == true | |
} | |
@function _get-initialize-test ($map, $map-chain) { | |
$errors: false; | |
@if type-of($map) != map { | |
@warn "$map needs to be a map. Currently it's a #{type-of($map)}"; | |
$errors: true; | |
} | |
@return $errors; | |
} | |
@function _get-map-keys-test ($map, $key) { | |
$errors: false; | |
@if type-of($map) != map { | |
@warn "_get-map-keys-test(): $map is not a map"; | |
$errors: true; | |
} | |
@if not map-has-key($map, $key) { | |
@warn "Map doesn't have a key named '#{$key}'!! Available keys include: '#{map-keys($map)}'"; | |
$errors: true; | |
} | |
@return $errors; | |
} | |
// ------------------------------------------------ | |
// Get the first key or value from a list or map | |
// | |
// @param {List|Map} $collection - List or Map | |
// @param {String} $return - What to return: key or value | |
// | |
// @requires _get-in-collection-unit-tests() | |
@function get-first ($collection, $return: key) { | |
$return: to-lower_case($return); | |
$errors: _get-in-collection-unit-tests($collection, $return); | |
@if not $errors { | |
@if type-of($collection) == list { | |
@return nth($collection, 1) | |
} | |
@else { | |
@if $return == 'key' { | |
@return (nth(map-keys($collection), 1)); | |
} | |
@else { | |
@return map-get($collection, nth(map-keys($collection), 1)); | |
} | |
} | |
} | |
@else { | |
@return false; | |
} | |
} | |
// ------------------------------------------------ | |
// Get the last key or value from a list or map | |
// | |
// @param {List|Map} $collection - List or Map | |
// @param {String} $return - What to return: key or value | |
// | |
// @requires _get-in-collection-unit-tests() | |
@function get-last ($collection, $return: key) { | |
$return: to-lower_case($return); | |
$errors: _get-in-collection-unit-tests($collection, $return); | |
@if not $errors { | |
@if type-of($collection) == list { | |
@return nth($collection, length($collection)) | |
} | |
@else { | |
@if $return == 'key' { | |
@return nth(map-keys($collection), length($collection)); | |
} | |
@else { | |
@return map-get($collection, nth(map-keys($collection), length($collection))); | |
} | |
} | |
} | |
@else { | |
@return false; | |
} | |
} | |
@function _get-in-collection-unit-tests ($collection, $return) { | |
$collection-types: (list, map); | |
$returns: (key, value); | |
@if not index($collection-types, type-of($collection)) { | |
@warn ('$collection needs to be one of the following: #{$collection-types}. Was a: #{type-of($collection)}'); | |
@return true; | |
} | |
@if $return and not index($returns, $return) { | |
@warn ('$return was: #{$return}, but needs to be one of the following: #{$returns}'); | |
@return true; | |
} | |
@if type-of($collection) == list and $return == value { | |
@warn "$collection is a list, which doesn't have values"; | |
@return true; | |
} | |
@return false; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment