aboutsummaryrefslogtreecommitdiffstats
path: root/src/_functions.scss
diff options
context:
space:
mode:
Diffstat (limited to 'src/_functions.scss')
-rw-r--r--src/_functions.scss328
1 files changed, 328 insertions, 0 deletions
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 @@
1////
2/// Various functions.
3///
4/// This file contains various and mostly unrelated functions. Some of which
5/// are used in this framework, while others are just there and may be used.
6///
7/// @group Functions
8///
9/// @access public
10////
11
12///
13/// Replace a substring with a new string.
14///
15/// @param {string} $string - String to search
16/// @param {string} $search - Substring that gets replaced
17/// @param {string} $replace - String that replaces $search
18///
19/// @return {string} A string with all instances of $search replaced with $replace
20///
21@function iro-str-replace($string, $search, $replace) {
22 $index: str-index($string, $search);
23
24 @if $index {
25 @return str-slice($string, 1, $index - 1) + $replace + iro-str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
26 }
27
28 @return $string;
29}
30
31///
32/// Concatenate all items from $list.
33///
34/// @param {list} $list
35/// @param {number} $glue - Delimiter
36///
37/// @return {string}
38///
39@function iro-str-implode($list, $glue: '') {
40 $result: '';
41
42 @each $item in $list {
43 $result: $result + if(length($item) > 1, iro-str-implode($item, $glue), $item);
44
45 @if $item != nth($list, length($list)) {
46 $result: $result + $glue;
47 }
48 }
49
50 @return $result;
51}
52
53///
54/// Extract a subset from the given list.
55///
56/// @param {list} $list
57/// @param {number} $start [1] - Indices before this value will be discarded
58/// @param {number} $end [length($list)] - Indices starting after this value will be discarded
59///
60/// @return {list} A slice of the list
61///
62@function iro-list-slice($list, $start: 1, $end: length($list)) {
63 $result: ();
64
65 @for $i from $start through $end {
66 @if $i != 0 {
67 $result: append($result, nth($list, $i), list-separator($list));
68 }
69 }
70
71 @return $result;
72}
73
74///
75/// Add a new item to the beginning of a list.
76///
77/// @param {list} $list
78/// @param {number} $value
79///
80/// @return {list} A list with $value at the beginning, followed by the other items
81///
82@function iro-list-prepend($list, $value) {
83 $result: append((), $value, list-separator($list));
84
85 @if length($list) > 0 {
86 @for $i from 1 through length($list) {
87 $result: append($result, nth($list, $i), list-separator($list));
88 }
89 }
90
91 @return $result;
92}
93
94///
95/// Sort numeric items in a list.
96///
97/// The implementation is based on the algorithm on the German Wikipedia article
98/// about quicksort: https://de.wikipedia.org/wiki/Quicksort#Pseudocode
99///
100/// @param {list} $l
101///
102/// @return {list} Sorted list
103///
104@function iro-quicksort($l, $left: 1, $right: length($l)) {
105 @if $left < $right {
106 $pvr: iro-quicksort-partition($l, $left, $right);
107 $pivot: nth($pvr, 1);
108 $l: nth($pvr, 2);
109 $l: iro-quicksort($l, $left, $pivot);
110 $l: iro-quicksort($l, $pivot + 1, $right);
111 }
112
113 @return $l;
114}
115
116///
117/// @access private
118///
119@function iro-quicksort-partition($l, $left, $right) {
120 $start: true;
121 $i: $left;
122 $j: $right - 1;
123 $pivot: nth($l, $right);
124
125 @while ($i < $j) or $start {
126 @while (nth($l, $i) < $pivot) and ($i < $right - 1) {
127 $i: $i + 1;
128 }
129
130 @while (nth($l, $j)>= $pivot) and ($j > $left) {
131 $j: $j - 1;
132 }
133
134 @if $i < $j {
135 $i-val: nth($l, $i);
136 $l: set-nth($l, $i, nth($l, $j));
137 $l: set-nth($l, $j, $i-val);
138 }
139
140 $start: false;
141 }
142
143 @if nth($l, $i) > $pivot {
144 $i-val: nth($l, $i);
145 $l: set-nth($l, $i, nth($l, $right));
146 $l: set-nth($l, $right, $i-val);
147 }
148
149 @return $i $l;
150}
151
152///
153/// Try to get the value for the given key from the given map. If it doesn't contain that key,
154/// return the provided default value instead.
155///
156/// @param {map} $map
157/// @param {string} $key
158/// @param {any} $default
159///
160/// @return {any} Either the value assigned to $key or $default
161///
162@function iro-map-get-default($map, $key, $default) {
163 @return if(map-has-key($map, $key), map-get($map, $key), $default);
164}
165
166///
167/// Get the value for a map within a map (or deeper).
168///
169/// @param {map} $map
170/// @param {string | list} $key
171/// @param {any} $default [null]
172///
173/// @return {any} Either the value assigned to $key or $default
174///
175@function iro-map-get-deep($map, $key, $default: null) {
176 $value: null;
177
178 @if type-of($key) == list {
179 $value: $map;
180
181 @each $k in $key {
182 $value: map-get($value, $k);
183
184 @if $value == null {
185 @return $default;
186 }
187 }
188 } @else {
189 $value: map-get($map, $key);
190
191 @if $value == null {
192 @return $default;
193 }
194 }
195
196 @return $value;
197}
198
199///
200/// Merge two maps recursively.
201///
202/// @param {map} $map1
203/// @param {map} $map2
204///
205/// @return {map} The result of a recursive merge of $map1 and $map2
206///
207@function iro-map-merge-recursive($map1, $map2) {
208 @if type-of($map1) != map or type-of($map2) != map {
209 @error 'Two maps expected.';
210 }
211
212 $result: $map1;
213
214 @each $key, $value in $map2 {
215 @if type-of(map-get($result, $key)) == map and type-of($value) == map {
216 $result: map-merge($result, ($key: iro-map-merge-recursive(map-get($result, $key), $value)));
217 } @else {
218 $result: map-merge($result, ($key: $value));
219 }
220 }
221
222 @return $result;
223}
224
225///
226/// Get the contents of a map as a user-friendly string representation.
227///
228/// @param {map} $map
229///
230/// @return {string}
231///
232@function iro-map-print($map) {
233 $output: '';
234
235 @each $key, $value in $map {
236 $value-str: '';
237
238 @if type-of($value) == map {
239 $value-str: '[ ' + iro-map-print($value) + ' ]';
240 } @else if type-of($value) == list {
241 $value-str: '[ ' + iro-str-implode($value, ', ') + ' ]';
242 } @else if type-of($value) == string {
243 $value-str: '\'' + $value + '\'';
244 } @else {
245 $value-str: $value;
246 }
247
248 @if $output == '' {
249 $output: $key + ': ' + $value-str;
250 } @else {
251 $output: $output + ', ' + $key + ': ' + $value-str;
252 }
253 }
254
255 @return $output;
256}
257
258///
259/// Check if the given selector ends with one of the provided suffixes.
260///
261/// @param {selector} $selector
262/// @param {selector} $suffixes
263///
264/// @return {bool} `true` if the selector matches at least one suffix, otherwise `false`.
265///
266@function iro-selector-suffix-match($selector, $suffixes) {
267 $match: true;
268
269 @each $sel in $selector {
270 @if $match {
271 $sel-match: false;
272
273 @each $suffix in $suffixes {
274 @if not $sel-match {
275 $suf-match: true;
276
277 @for $i from 1 through length($suffix) {
278 @if $suf-match and (nth($sel, -$i) != nth($suffix, -$i)) {
279 $suf-match: false;
280 }
281 }
282
283 @if $suf-match {
284 $sel-match: true;
285 }
286 }
287 }
288
289 @if not $sel-match {
290 $match: false;
291 }
292 }
293 }
294
295 @return $match;
296}
297
298///
299/// Remove the unit from any variable.
300///
301/// @param {any} $n
302///
303/// @return {number} Unit-less variable
304///
305@function iro-strip-unit($n) {
306 @return $n / ($n * 0 + 1);
307}
308
309///
310/// Convert a pixel value to a rem value.
311///
312/// @param {number} $size - Pixel value to convert
313/// @param {number} $base [$iro-root-size] - Reference base font size used for conversion
314///
315/// @return {number} Pixel value converted to rem
316///
317@function iro-px-to-rem($size, $base: $iro-root-size) {
318 @return $size / $base * 1rem;
319}
320
321///
322/// A mixin with the sole purpose of letting you use temporary variables without polluting the global namespace.
323///
324/// @content
325///
326@mixin iro-execute {
327 @content;
328}