Source: util.styl

/**
 * @namespace Util
 */



/**
 * @namespace Util:hash-get-deep
 */

/**
 * Retrieve a value deeply nested in a hash, defined by a path of keys.
 *
 * @memberof Util:hash-get-deep
 * @function
 * @name hash-get-deep
 * @alias hash-get-deep
 *
 * @param {Hash} $hash - the hash to search in
 * @param {String|List<String>} $keys - the keys to traverse down in the hash
 * @returns {*|null} the value at the defined key path or null if not defined
 *
 * @example
 * hash-get-deep($foo-hash, 'level1', 'level2')
 *   => value of $foo-hash.level1.level2
 */
hash-get-deep($hash, $keys...)
	for $key in $keys
		if $key in $hash
			$hash = $hash[$key]
		else
			return null

	return $hash



/**
 * @namespace Util:hash-next
 */

/**
 * Retrieves the value of the adjacent, next key in a hash, if one exists.
 * The idea is, to retrieve the next key, based on a current one, to go one step further,
 * which is helpful for things like escalating to the next breakpoint for example.
 *
 * @memberof Util:hash-next
 * @function
 * @name hash-next
 * @alias hash-next
 *
 * @param {Hash} $hash - the hash to use
 * @param {String} $key - the current key, from which we want to go to the next
 * @returns {*|null} the value of the next key or null if there is none
 *
 * @example
 * hash-next($foo-hash, 'small')
 *   => value of $foo-hash.medium
 */
hash-next($hash, $key)
	$keys = keys($hash)

	$next-index = 0
	if $key in $hash
		$next-index = index($keys, $key) + 1

	if ($next-index == 0) or ($next-index > (length($keys) - 1))
		return null
	else
		return $hash[$keys[$next-index]]



/**
 * @namespace Util:strip-unit
 */

/**
 * Removes the unit from a value, turning it into a unit-less value.
 *
 * @memberof Util:strip-unit
 * @function
 * @name strip-unit
 * @alias strip-unit
 *
 * @param {Number} $number - the number to strip the unit from
 * @returns {Number} the unit-less number
 *
 * @example
 * strip-unit(16px)
 *   => 16
 */
strip-unit($number)
	return unit($number, '')



/**
 * @namespace Util:to-rem
 */

/**
 * Convert one or more px values to (a) rem value(s), based on a base font size in px, percent or rem.
 * If the base is in % or rem, the base will be converted to px based on the global base font size.
 *
 * @memberof Util:to-rem
 * @function
 * @name to-rem
 * @alias to-rem
 *
 * @param {Number|List<Number>} $values - the value(s) to convert, usually px values, if a value is em, it will be treated as rem
 * @param {?Number} [$base=$jig---base-font-size-px] - the base size to convert against
 * @returns {Number|List<Number>} the converted value(s)
 *
 * @example
 * to-rem(32px)
 *   => 2rem
 * to-rem((10px, 20px, 40px), 20px)
 *   => (0.5rem, 1rem, 2rem)
 */
to-rem($values, $base=$jig---base-font-size)
	if unit($base) == '%'
		$base = (strip-unit($base) / 100) * $jig---base-font-size

	if unit($base) == 'rem'
		$base = strip-unit($base) * $jig---base-font-size

	$rem-values = ()
	for $value in $values
		$rem-value = 0

		if unit($value) == 'em'
			$rem-value = strip-unit($value)
		else
			$rem-value = strip-unit($value) / strip-unit($base)

		if $rem-value != 0
			$rem-value = ($rem-value)rem

		append($rem-values, $rem-value)

	if length($rem-values) == 1
		return $rem-values[0]
	else
		return $rem-values



/**
 * @namespace Util:to-em
 */

/**
 * Convert one or more px values to (a) em value(s), based on a base font size in px, percent or rem.
 * If the base is in % or rem, the base will be converted to px based on the global base font size.
 *
 * @memberof Util:to-em
 * @function
 * @name to-em
 * @alias to-em
 *
 * @param {Number|List<Number>} $values - the value(s) to convert, usually px values, if a value is em, it will not be changed
 * @param {Number} $base - the base size to convert against
 * @returns {Number|List<Number>} the converted value(s)
 *
 * @example
 * to-em(32px, 16px)
 *   => 2em
 * to-em((10px, 20px, 40px), 20px)
 *   => [0.5em, 1em, 2em]
 */
to-em($values, $base)
	$rem-values = to-rem($values, $base)

	$em-values = ()
	for $rem-value in $rem-values
		$em-value = 0

		if $rem-value != 0
			$em-value = (strip-unit($rem-value))em

		append($em-values, $em-value)

	if length($em-values) == 1
		return $em-values[0]
	else
		return $em-values



/**
 * @namespace Util:str-join
 */

/**
 * Join/concatenate two or more strings with an optional glue string.
 *
 * @memberof Util:str-join
 * @function
 * @name str-join
 * @alias str-join
 *
 * @param {String|List<String>} strings - the strings to join
 * @param {String} glue - the string to put between joined strings
 * @returns {String} the joined string
 *
 * @example
 * str-join(('fo', 'ar'), 'ob')
 *   => 'foobar'
 */
str-join($strings, $glue='')
	$res = ''
	for $string in $strings
		if $string
			$res += $string+$glue;

	if ($res != '') and ($glue != '')
		return slice($res, 0, length($glue) * -1)
	else
		return $res



/**
 * @namespace Util:to-str
 */

/**
 * Casts a value/literal to a string.
 *
 * @memberof Util:to-str
 * @function
 * @name to-str
 * @alias to-str
 *
 * @param {*} $value - the value to cast to string
 * @param {Boolean} $only-ident - if true, only casts if value is an ident
 * @returns {String} the stringified value
 *
 * @example
 * to-str(medium)
 *   => 'medium'
 */
to-str($value, $only-ident=false)
	if !$only-ident or ($only-ident and (type($value) == 'ident'))
		return ''+$value
	else
		return $value