From d07f664450ddaaebb44127a4bd057763d13d3f82 Mon Sep 17 00:00:00 2001 From: Feuerfuchs Date: Sun, 1 Nov 2020 20:55:14 +0100 Subject: Init --- src/_functions.scss | 328 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 328 insertions(+) create mode 100644 src/_functions.scss (limited to 'src/_functions.scss') diff --git a/src/_functions.scss b/src/_functions.scss new file mode 100644 index 0000000..2f34dc4 --- /dev/null +++ b/src/_functions.scss @@ -0,0 +1,328 @@ +//// +/// Various functions. +/// +/// This file contains various and mostly unrelated functions. Some of which +/// are used in this framework, while others are just there and may be used. +/// +/// @group Functions +/// +/// @access public +//// + +/// +/// Replace a substring with a new string. +/// +/// @param {string} $string - String to search +/// @param {string} $search - Substring that gets replaced +/// @param {string} $replace - String that replaces $search +/// +/// @return {string} A string with all instances of $search replaced with $replace +/// +@function iro-str-replace($string, $search, $replace) { + $index: str-index($string, $search); + + @if $index { + @return str-slice($string, 1, $index - 1) + $replace + iro-str-replace(str-slice($string, $index + str-length($search)), $search, $replace); + } + + @return $string; +} + +/// +/// Concatenate all items from $list. +/// +/// @param {list} $list +/// @param {number} $glue - Delimiter +/// +/// @return {string} +/// +@function iro-str-implode($list, $glue: '') { + $result: ''; + + @each $item in $list { + $result: $result + if(length($item) > 1, iro-str-implode($item, $glue), $item); + + @if $item != nth($list, length($list)) { + $result: $result + $glue; + } + } + + @return $result; +} + +/// +/// Extract a subset from the given list. +/// +/// @param {list} $list +/// @param {number} $start [1] - Indices before this value will be discarded +/// @param {number} $end [length($list)] - Indices starting after this value will be discarded +/// +/// @return {list} A slice of the list +/// +@function iro-list-slice($list, $start: 1, $end: length($list)) { + $result: (); + + @for $i from $start through $end { + @if $i != 0 { + $result: append($result, nth($list, $i), list-separator($list)); + } + } + + @return $result; +} + +/// +/// Add a new item to the beginning of a list. +/// +/// @param {list} $list +/// @param {number} $value +/// +/// @return {list} A list with $value at the beginning, followed by the other items +/// +@function iro-list-prepend($list, $value) { + $result: append((), $value, list-separator($list)); + + @if length($list) > 0 { + @for $i from 1 through length($list) { + $result: append($result, nth($list, $i), list-separator($list)); + } + } + + @return $result; +} + +/// +/// Sort numeric items in a list. +/// +/// The implementation is based on the algorithm on the German Wikipedia article +/// about quicksort: https://de.wikipedia.org/wiki/Quicksort#Pseudocode +/// +/// @param {list} $l +/// +/// @return {list} Sorted list +/// +@function iro-quicksort($l, $left: 1, $right: length($l)) { + @if $left < $right { + $pvr: iro-quicksort-partition($l, $left, $right); + $pivot: nth($pvr, 1); + $l: nth($pvr, 2); + $l: iro-quicksort($l, $left, $pivot); + $l: iro-quicksort($l, $pivot + 1, $right); + } + + @return $l; +} + +/// +/// @access private +/// +@function iro-quicksort-partition($l, $left, $right) { + $start: true; + $i: $left; + $j: $right - 1; + $pivot: nth($l, $right); + + @while ($i < $j) or $start { + @while (nth($l, $i) < $pivot) and ($i < $right - 1) { + $i: $i + 1; + } + + @while (nth($l, $j)>= $pivot) and ($j > $left) { + $j: $j - 1; + } + + @if $i < $j { + $i-val: nth($l, $i); + $l: set-nth($l, $i, nth($l, $j)); + $l: set-nth($l, $j, $i-val); + } + + $start: false; + } + + @if nth($l, $i) > $pivot { + $i-val: nth($l, $i); + $l: set-nth($l, $i, nth($l, $right)); + $l: set-nth($l, $right, $i-val); + } + + @return $i $l; +} + +/// +/// Try to get the value for the given key from the given map. If it doesn't contain that key, +/// return the provided default value instead. +/// +/// @param {map} $map +/// @param {string} $key +/// @param {any} $default +/// +/// @return {any} Either the value assigned to $key or $default +/// +@function iro-map-get-default($map, $key, $default) { + @return if(map-has-key($map, $key), map-get($map, $key), $default); +} + +/// +/// Get the value for a map within a map (or deeper). +/// +/// @param {map} $map +/// @param {string | list} $key +/// @param {any} $default [null] +/// +/// @return {any} Either the value assigned to $key or $default +/// +@function iro-map-get-deep($map, $key, $default: null) { + $value: null; + + @if type-of($key) == list { + $value: $map; + + @each $k in $key { + $value: map-get($value, $k); + + @if $value == null { + @return $default; + } + } + } @else { + $value: map-get($map, $key); + + @if $value == null { + @return $default; + } + } + + @return $value; +} + +/// +/// Merge two maps recursively. +/// +/// @param {map} $map1 +/// @param {map} $map2 +/// +/// @return {map} The result of a recursive merge of $map1 and $map2 +/// +@function iro-map-merge-recursive($map1, $map2) { + @if type-of($map1) != map or type-of($map2) != map { + @error 'Two maps expected.'; + } + + $result: $map1; + + @each $key, $value in $map2 { + @if type-of(map-get($result, $key)) == map and type-of($value) == map { + $result: map-merge($result, ($key: iro-map-merge-recursive(map-get($result, $key), $value))); + } @else { + $result: map-merge($result, ($key: $value)); + } + } + + @return $result; +} + +/// +/// Get the contents of a map as a user-friendly string representation. +/// +/// @param {map} $map +/// +/// @return {string} +/// +@function iro-map-print($map) { + $output: ''; + + @each $key, $value in $map { + $value-str: ''; + + @if type-of($value) == map { + $value-str: '[ ' + iro-map-print($value) + ' ]'; + } @else if type-of($value) == list { + $value-str: '[ ' + iro-str-implode($value, ', ') + ' ]'; + } @else if type-of($value) == string { + $value-str: '\'' + $value + '\''; + } @else { + $value-str: $value; + } + + @if $output == '' { + $output: $key + ': ' + $value-str; + } @else { + $output: $output + ', ' + $key + ': ' + $value-str; + } + } + + @return $output; +} + +/// +/// Check if the given selector ends with one of the provided suffixes. +/// +/// @param {selector} $selector +/// @param {selector} $suffixes +/// +/// @return {bool} `true` if the selector matches at least one suffix, otherwise `false`. +/// +@function iro-selector-suffix-match($selector, $suffixes) { + $match: true; + + @each $sel in $selector { + @if $match { + $sel-match: false; + + @each $suffix in $suffixes { + @if not $sel-match { + $suf-match: true; + + @for $i from 1 through length($suffix) { + @if $suf-match and (nth($sel, -$i) != nth($suffix, -$i)) { + $suf-match: false; + } + } + + @if $suf-match { + $sel-match: true; + } + } + } + + @if not $sel-match { + $match: false; + } + } + } + + @return $match; +} + +/// +/// Remove the unit from any variable. +/// +/// @param {any} $n +/// +/// @return {number} Unit-less variable +/// +@function iro-strip-unit($n) { + @return $n / ($n * 0 + 1); +} + +/// +/// Convert a pixel value to a rem value. +/// +/// @param {number} $size - Pixel value to convert +/// @param {number} $base [$iro-root-size] - Reference base font size used for conversion +/// +/// @return {number} Pixel value converted to rem +/// +@function iro-px-to-rem($size, $base: $iro-root-size) { + @return $size / $base * 1rem; +} + +/// +/// A mixin with the sole purpose of letting you use temporary variables without polluting the global namespace. +/// +/// @content +/// +@mixin iro-execute { + @content; +} -- cgit v1.2.3-54-g00ecf