@omnisass/library 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +21 -0
  3. package/README.md +2 -0
  4. package/_configs.scss +68 -0
  5. package/index.scss +95 -0
  6. package/modules/utilities/converters/_convert-camel2kebab.scss +186 -0
  7. package/modules/utilities/converters/_convert-em2px.scss +239 -0
  8. package/modules/utilities/converters/_convert-hex2rgb.scss +97 -0
  9. package/modules/utilities/converters/_convert-hex2rgba.scss +124 -0
  10. package/modules/utilities/converters/_convert-kebab2camel.scss +232 -0
  11. package/modules/utilities/converters/_convert-kebab2snake.scss +118 -0
  12. package/modules/utilities/converters/_convert-px2em.scss +236 -0
  13. package/modules/utilities/converters/_convert-px2rem.scss +180 -0
  14. package/modules/utilities/converters/_convert-rem2px.scss +207 -0
  15. package/modules/utilities/converters/_convert-snake2kebab.scss +173 -0
  16. package/modules/utilities/getters/color/_get-color-brightness.scss +138 -0
  17. package/modules/utilities/getters/color/_get-color-darkest.scss +178 -0
  18. package/modules/utilities/getters/list/_get-list-item-end.scss +114 -0
  19. package/modules/utilities/getters/list/_get-list-item-start.scss +109 -0
  20. package/modules/utilities/getters/list/_get-list-item.scss +179 -0
  21. package/modules/utilities/getters/number/_get-number-from-percent.scss +139 -0
  22. package/modules/utilities/getters/number/_get-number-height-by-ratio.scss +199 -0
  23. package/modules/utilities/getters/number/_get-number-max.scss +168 -0
  24. package/modules/utilities/getters/number/_get-number-min.scss +162 -0
  25. package/modules/utilities/getters/number/_get-number-percentage-of.scss +149 -0
  26. package/modules/utilities/getters/number/_get-number-unit.scss +111 -0
  27. package/modules/utilities/getters/number/_get-number-width-by-ratio.scss +223 -0
  28. package/modules/utilities/helpers/color/_color-blend-steps.scss +210 -0
  29. package/modules/utilities/helpers/color/_color-blend.scss +183 -0
  30. package/modules/utilities/helpers/color/_color-hue-shift.scss +148 -0
  31. package/modules/utilities/helpers/color/_color-scale.scss +208 -0
  32. package/modules/utilities/helpers/color/_color-shade.scss +113 -0
  33. package/modules/utilities/helpers/color/_color-tint.scss +118 -0
  34. package/modules/utilities/helpers/color/_color-triad.scss +141 -0
  35. package/modules/utilities/helpers/list/_list-dedupe.scss +146 -0
  36. package/modules/utilities/helpers/list/_list-insert-at.scss +166 -0
  37. package/modules/utilities/helpers/list/_list-merge.scss +86 -0
  38. package/modules/utilities/helpers/list/_list-remove-at.scss +160 -0
  39. package/modules/utilities/helpers/list/_list-sum-numbers-safe.scss +175 -0
  40. package/modules/utilities/helpers/list/_list-sum-numbers.scss +128 -0
  41. package/modules/utilities/helpers/misc/_url-encode.configs.scss +64 -0
  42. package/modules/utilities/helpers/misc/_url-encode.scss +148 -0
  43. package/modules/utilities/helpers/number/_number-ceil-to.scss +111 -0
  44. package/modules/utilities/helpers/number/_number-clamp-max.scss +92 -0
  45. package/modules/utilities/helpers/number/_number-clamp-min.scss +100 -0
  46. package/modules/utilities/helpers/number/_number-clamp.scss +109 -0
  47. package/modules/utilities/helpers/number/_number-denormalize.scss +172 -0
  48. package/modules/utilities/helpers/number/_number-fibonacci.scss +235 -0
  49. package/modules/utilities/helpers/number/_number-floor-to.scss +114 -0
  50. package/modules/utilities/helpers/number/_number-format-with-separator.scss +122 -0
  51. package/modules/utilities/helpers/number/_number-normalize.scss +160 -0
  52. package/modules/utilities/helpers/number/_number-random-between-int.scss +84 -0
  53. package/modules/utilities/helpers/number/_number-random-between.scss +120 -0
  54. package/modules/utilities/helpers/number/_number-range.scss +268 -0
  55. package/modules/utilities/helpers/number/_number-round-to-nearest.scss +131 -0
  56. package/modules/utilities/helpers/number/_number-round-to.scss +118 -0
  57. package/modules/utilities/helpers/number/_number-strip-unit.scss +97 -0
  58. package/modules/utilities/helpers/string/_string-capitalize.scss +84 -0
  59. package/modules/utilities/helpers/string/_string-replace.scss +69 -0
  60. package/modules/utilities/helpers/string/_string-trim-end.scss +62 -0
  61. package/modules/utilities/helpers/string/_string-trim-start.scss +62 -0
  62. package/modules/utilities/helpers/string/_string-trim.scss +69 -0
  63. package/modules/utilities/loggers/_log-invalid-type.scss +151 -0
  64. package/modules/utilities/loggers/_log-invalid-value.scss +151 -0
  65. package/modules/utilities/setters/_index.scss +3 -0
  66. package/modules/utilities/validators/color/_is-color-light.scss +132 -0
  67. package/modules/utilities/validators/color/_is-color-list.scss +124 -0
  68. package/modules/utilities/validators/list/_is-list-contained.scss +65 -0
  69. package/modules/utilities/validators/misc/_is-time.scss +115 -0
  70. package/modules/utilities/validators/number/_is-int-even.scss +69 -0
  71. package/modules/utilities/validators/number/_is-int-odd.scss +70 -0
  72. package/modules/utilities/validators/number/_is-int.scss +124 -0
  73. package/modules/utilities/validators/number/_is-number-has-unit.scss +85 -0
  74. package/modules/utilities/validators/number/_is-number-negative.scss +76 -0
  75. package/modules/utilities/validators/number/_is-number-positive.scss +74 -0
  76. package/modules/utilities/validators/number/_is-number-unitless.scss +88 -0
  77. package/modules/utilities/validators/number/_is-number-zero.scss +75 -0
  78. package/modules/utilities/validators/string/_is-string-contained.scss +108 -0
  79. package/modules/utilities/validators/string/_is-string-empty.scss +56 -0
  80. package/modules/utilities/validators/string/_is-string-ending-with.scss +66 -0
  81. package/modules/utilities/validators/string/_is-string-starting-with.scss +66 -0
  82. package/modules/utilities/validators/type-of/_is-boolean.scss +92 -0
  83. package/modules/utilities/validators/type-of/_is-color.scss +96 -0
  84. package/modules/utilities/validators/type-of/_is-list.scss +105 -0
  85. package/modules/utilities/validators/type-of/_is-map.scss +105 -0
  86. package/modules/utilities/validators/type-of/_is-number.scss +103 -0
  87. package/modules/utilities/validators/type-of/_is-string.scss +110 -0
  88. package/modules/utilities/validators/type-of/_is-type.scss +77 -0
  89. package/package.json +54 -0
  90. package/package.scss +156 -0
  91. package/test.md +168 -0
  92. package/test.scss +405 -0
  93. package/test.sh +149 -0
@@ -0,0 +1,109 @@
1
+ @use 'sass:list';
2
+ @use '../../loggers/log-invalid-type' as *;
3
+ @use '../../validators/type-of/is-list' as *;
4
+
5
+ /// Возвращает первый элемент списка.
6
+ ///
7
+ /// Функция извлекает первый элемент из переданного списка.
8
+ /// Работает с любыми типами списков: разделенными запятыми,
9
+ /// пробелами или скобками.
10
+ ///
11
+ /// > Функция является оберткой над встроенной функцией `nth()`.
12
+ /// > Используйте `get-list-item-start()` для лучшей читаемости кода.
13
+ /// ---
14
+ /// @name get-list-item-start
15
+ /// @group utilities-getters
16
+ /// @since 2025.12.27
17
+ /// @access public
18
+ /// @author Sindre Sorhus
19
+ /// @author Murad Rustamov (therteenten) [адаптация]
20
+ /// @link https://github.com/sindresorhus GitHub - Sindre Sorhus
21
+ /// @link https://sourcecraft.dev/users/therteenten/overview SourceCraft - therteenten
22
+ /// @link https://sourcecraft.dev/omnisass/library SourceCraft - OmniSass
23
+ /// @link https://sass-lang.com/documentation/modules/list#nth См. также: Официальная документация Sass - Функция `list.nth()`
24
+ /// @link https://sass-lang.com/documentation/values/lists См. также: Официальная документация Sass - Тип данных "Списки" (Lists)
25
+ /// @link https://sass-lang.com/documentation/modules/list См. также: Официальная документация Sass - Модуль list
26
+ /// @link https://sass-lang.com/documentation/at-rules/function См. также: Официальная документация Sass - Правило `@function`
27
+ /// @link https://sass-lang.com/documentation/style-rules/declarations#custom-properties См. также: См. также: Документация Sass - Пользовательские функции
28
+ /// @link https://developer.mozilla.org/ru/docs/Web/CSS/list-style-type См. также: MDN Web Docs - CSS свойство `list-style-type`
29
+ /// @link https://developer.mozilla.org/ru/docs/Web/CSS/CSS_lists См. также: MDN Web Docs - Работа со списками в CSS
30
+ /// @link https://www.w3schools.com/sass/sass_functions_list.php См. также: W3Schools - Функции для работы со списками в Sass
31
+ /// @link https://www.sass.hk/docs/ См. также: Китайская документация Sass - Полное руководство
32
+ /// @link https://sass-guidelin.es/ru/#section-39 См. также: Sass Guidelines - Раздел про пользовательские функции
33
+ /// @link https://github.com/sass/sass/blob/main/accepted/module-system.md См. также: GitHub - Документация по модульной системе Sass
34
+ /// @link https://stackoverflow.com/questions/36885966/sass-get-first-item-from-a-list См. также: Stack Overflow - Как получить первый элемент списка в Sass
35
+ /// @link https://stackoverflow.com/questions/16444456/sass-get-nth-child-using-variable См. также: Stack Overflow - Использование `nth()` с переменными
36
+ /// @link https://css-tricks.com/snippets/sass/ См. также: CSS-Tricks - Коллекция сниппетов Sass
37
+ /// @link https://web.dev/learn/css/lists/ См. также: web.dev - Изучение CSS списков
38
+ /// @link https://frontender.info/sass-lists/ См. также: Frontender Magazine - Работа со списками в Sass
39
+ /// @link https://habr.com/ru/post/156549/ См. также: Habr - Статья "Sass для верстальщика: списки и циклы"
40
+ /// @link https://www.sitepoint.com/using-sass-maps/ См. также: SitePoint - Использование карт (`maps`) в Sass
41
+ /// @link https://www.freecodecamp.org/news/how-to-use-lists-in-sass/ См. также: freeCodeCamp - Как использовать списки в Sass
42
+ /// @link https://code.tutsplus.com/tutorials/understanding-sass-lists--cms-22020 См. также: Envato Tuts+ - Понимание списков в Sass
43
+ /// @link https://dev.to/kathryngrayson/using-sass-list-functions-4lp См. также: Dev.to - Использование функций для работы со списками в Sass
44
+ /// @link https://css-live.ru/vecssti-i-sovety/vse-o-spiskax-v-sass.html См. также: CSS-Live - Все о списках в Sass
45
+ /// @link https://itchief.ru/sass/cycles-and-lists См. также: itchief - Циклы и списки в Sass
46
+ /// @link https://htmlacademy.ru/blog/boost/tools/sass-3 См. также: HTML Academy - Sass: списки, циклы, условия
47
+ /// @link https://metanit.com/web/html5/13.6.php См. также: Metanit - Списки и циклы в Sass
48
+ /// @link https://ru.hexlet.io/courses/sass-basics/lessons/conditionals/theory_unit См. также: Hexlet - Условные операторы и списки в Sass
49
+ /// @link https://www.youtube.com/watch?v=roywYSEPSvc См. также: YouTube - Sass Tutorial #10 - Lists (The Net Ninja)
50
+ /// @link https://www.youtube.com/watch?v=BIz02qY5BRA См. также: YouTube - Sass списки и циклы (на русском)
51
+ /// @link https://codelabs.developers.google.com/codelabs/cloud-sass-cli#5 См. также: Google Codelabs - Создание пользовательских функций в Sass
52
+ /// @link https://www.npmjs.com/package/sass См. также: npm - Документация пакета Dart Sass
53
+ /// @link https://marketplace.visualstudio.com/items?itemName=Syler.sass-indented См. также: VS Code Marketplace - Поддержка синтаксиса Sass
54
+ /// @link https://stylelint.io/user-guide/rules/list/ См. также: Stylelint - Правила для работы со списками
55
+ /// @link https://sass-lang.com/documentation/js-api См. также: JavaScript API - Работа с Sass через JavaScript
56
+ /// @link https://sass-lang.com/documentation/cli/dart-sass См. также: CLI - Командная строка Dart Sass
57
+ /// @link https://sass-lang.com/documentation/breaking-changes/module-system См. также: Breaking Changes - Изменения в модульной системе
58
+ /// @link https://sass-lang.com/documentation/values/numbers#units См. также: Документация Sass - Числа и единицы измерения
59
+ /// @link https://sass-lang.com/documentation/values/strings См. также: Документация Sass - Строки
60
+ /// @link https://sass-lang.com/documentation/values/booleans См. также: Документация Sass - Логические значения
61
+ /// @link https://sass-lang.com/documentation/values/null См. также: Документация Sass - Значение `null`
62
+ /// @link https://sass-lang.com/documentation/values/maps См. также: Документация Sass - Карты (`maps`)
63
+ /// @link https://sass-lang.com/documentation/interpolation См. также: Документация Sass - Интерполяция
64
+ /// @example scss - Извлечение первого элемента
65
+ /// @debug get-list-item-start(apple banana cherry); // apple
66
+ /// @debug get-list-item-start((1, 2, 3, 4)); // 1
67
+ /// @debug get-list-item-start(red blue green); // red
68
+ /// @debug get-list-item-start(("one", "two", "three")); // "one"
69
+ /// @example scss - Использование в условных конструкциях
70
+ /// $colors: red, blue, green;
71
+ /// $primary: get-list-item-start($colors); // $primary: red
72
+ /// @example scss - Обработка пустого списка
73
+ /// @debug get-list-item-start(()); // error
74
+ /// @debug get-list-item-start(none); // null
75
+ /// @see get-list-item-end
76
+ /// @param {List} $list - Список, из которого нужно извлечь
77
+ /// первый элемент.
78
+ /// @return {*} - Первый элемент списка. Возвращает `null`,
79
+ /// если список пустой.
80
+ /// @throws Не выбрасывает ошибки, но возвращает
81
+ /// `null` для пустых списков.
82
+ @function get-list-item-start($list) {
83
+
84
+ @if not is-list($list) {
85
+
86
+ // Валидация типа входного параметра.
87
+ // Функция ожидает получить список (list) или arglist.
88
+ @return log-invalid-type(
89
+ 'get-list-item-start',
90
+ $list,
91
+ '$list',
92
+ ('list', 'arglist')
93
+ );
94
+
95
+ } @else {
96
+
97
+ // Основная логика выполняется только если $list является
98
+ // корректным списком.
99
+ //
100
+ // Используем встроенную функцию Sass list.nth():
101
+ // - Извлекает элемент по указанному индексу (в данном
102
+ // случае 1 - первый)
103
+ // - Для пустого списка возвращает null
104
+ // - Сохраняет тип и значение элемента без изменений
105
+ @return list.nth($list, 1);
106
+
107
+ }
108
+
109
+ }
@@ -0,0 +1,179 @@
1
+ @use 'sass:list';
2
+ @use 'sass:map';
3
+ @use './get-list-item-start' as *;
4
+ @use './get-list-item-end' as *;
5
+ @use '../../loggers/log-invalid-value' as *;
6
+ @use '../../loggers/log-invalid-type' as *;
7
+ @use '../../validators/type-of/is-string' as *;
8
+
9
+ /// Возвращает первый или последний элемент списка.
10
+ ///
11
+ /// Функция предоставляет удобный способ получения крайних
12
+ /// элементов списка с явным указанием, какой именно элемент
13
+ /// нужен - первый (начальный) или последний (конечный).
14
+ /// Это упрощает код и делает его более читаемым по
15
+ /// сравнению с прямым использованием `list.nth()` с
16
+ /// индексами `1` или `-1`.
17
+ ///
18
+ /// Важные особенности функции:
19
+ /// - Поддерживает получение как первого, так и последнего
20
+ /// элемента
21
+ /// - Возвращает `null` для некорректных значений параметра
22
+ /// `$direction`
23
+ /// - Обрабатывает пустые списки (возвращает `null`)
24
+ /// - Использует встроенные функции модуля `list` для
25
+ /// надежности
26
+ /// - Имеет понятный интерфейс с именованными параметрами
27
+ /// - Сохраняет тип и значение исходного элемента
28
+ /// ---
29
+ /// @name get-list-item
30
+ /// @group utilities-getters
31
+ /// @since 2025.12.27
32
+ /// @access public
33
+ /// @author Murad Rustamov (therteenten)
34
+ /// @link https://sourcecraft.dev/users/therteenten/overview SourceCraft - therteenten
35
+ /// @link https://sourcecraft.dev/omnisass/library SourceCraft - OmniSass
36
+ /// @link https://sass-lang.com/documentation/values/lists См. также: Официальная документация Sass - Списки
37
+ /// @link https://sass-lang.com/documentation/modules/list См. также: Официальная документация Sass - Модуль list
38
+ /// @link https://sass-lang.com/documentation/modules/list#nth См. также: Официальная документация Sass - Функция list.nth()
39
+ /// @link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Lists_and_Counters/Using_CSS_counters См. также: MDN Web Docs - CSS списки и счетчики
40
+ /// @link https://css-tricks.com/snippets/sass/ См. также: CSS-Tricks - Коллекция сниппетов Sass
41
+ /// @link https://sass-guidelin.es/ru/#section-43 См. также: Sass Guidelines - Раздел про списки
42
+ /// @link https://www.w3schools.com/sass/sass_lists.php См. также: W3Schools - Списки в Sass
43
+ /// @example scss - Получение первого элемента (по умолчанию)
44
+ /// @debug get-list-item((a, b, c, d, e)); // "a"
45
+ /// @debug get-list-item((a, b, c, d, e), "start"); // "a"
46
+ /// @debug get-list-item(("first", "second", "third")); // "first"
47
+ /// @debug get-list-item((1px, 2px, 3px, 4px)); // 1px
48
+ /// @debug get-list-item(((1, 2), (3, 4), (5, 6))); // (1, 2)
49
+ /// @example scss - Получение последнего элемента
50
+ /// @debug get-list-item((a, b, c, d, e), "end"); // "e"
51
+ /// @debug get-list-item(("first", "second", "third"), "end"); // "third"
52
+ /// @debug get-list-item((1px, 2px, 3px, 4px), "end"); // 4px
53
+ /// @debug get-list-item(((1, 2), (3, 4), (5, 6)), "end"); // (5, 6)
54
+ /// @example scss - Списки из одного элемента
55
+ /// @debug get-list-item((only-item,)); // "only-item"
56
+ /// @debug get-list-item((only-item,), "start"); // "only-item"
57
+ /// @debug get-list-item((only-item,), "end"); // "only-item"
58
+ /// @debug get-list-item((42,)); // 42
59
+ /// @example scss - Пустые списки
60
+ /// @debug get-list-item(()); // Error: список не должен быть пустым
61
+ /// @debug get-list-item((), "start"); // Error: список не должен быть пустым
62
+ /// @debug get-list-item((), "end"); // Error: список не должен быть пустым
63
+ /// @example scss - Некорректные значения направления
64
+ /// @debug get-list-item((a, b, c), "middle"); // null
65
+ /// @debug get-list-item((a, b, c), "center"); // null
66
+ /// @debug get-list-item((a, b, c), ""); // null
67
+ /// @debug get-list-item((a, b, c), null); // null
68
+ /// @debug get-list-item((a, b, c), 1); // null
69
+ /// @debug get-list-item((a, b, c), true); // null
70
+ /// @example scss - Списки с разделителями
71
+ /// @debug get-list-item([a, b, c, d, e]); // Error: квадратные скобки
72
+ /// @debug get-list-item([a, b, c, d, e], "end"); // Error: квадратные скобки
73
+ /// @debug get-list-item((a b c d e)); // "a" (разделитель пробел)
74
+ /// @debug get-list-item((a b c d e), "end"); // "e"
75
+ /// @see get-list-item-start
76
+ /// @see get-list-item-end
77
+ /// @param {List} $list - Список, из которого нужно получить
78
+ /// элемент. Может быть списком любого типа элементов,
79
+ /// включая вложенные списки. Для пустых списков функция
80
+ /// возвращает `null`.
81
+ /// @param {String} $direction ["start"] - Направление,
82
+ /// указывающее какой элемент нужно получить. Допустимые
83
+ /// значения:
84
+ /// - `"start"` (по умолчанию) - получить первый элемент списка
85
+ /// - `"end"` - получить последний элемент списка
86
+ /// Для любых других значений функция возвращает `null`.
87
+ /// @return {*} - Элемент списка в указанной позиции. Для
88
+ /// `$direction: "start"` возвращает первый элемент, для
89
+ /// `$direction: "end"` - последний элемент. Возвращает
90
+ /// `null` для пустых списков, некорректных значений
91
+ /// `$direction` или если список не содержит элементов
92
+ /// в указанной позиции.
93
+ /// @throws Не выбрасывает ошибок, безопасно обрабатывает
94
+ /// некорректные входные данные. Для пустых списков и
95
+ /// некорректных значений `$direction` возвращает `null`.
96
+ @function get-list-item($list, $direction: 'start') {
97
+
98
+ // Переменная для хранения результата функции
99
+ // Инициализируем пустой строкой, но тип может
100
+ // измениться в зависимости от функций get-list-item-start/end
101
+ $-result: '';
102
+
103
+ // ВАЛИДАЦИЯ ПАРАМЕТРА $direction
104
+
105
+ // 1. Проверка типа: параметр `$direction` должен быть строкой.
106
+ // Используем вспомогательную функцию is-string. Если тип не
107
+ // `string`, выводим отладочное сообщение через
108
+ // `log-invalid-type`:
109
+ @if not is-string($direction) {
110
+ @debug log-invalid-type(
111
+ 'get-list-item',
112
+ $direction,
113
+ '$direction',
114
+ 'string'
115
+ );
116
+ }
117
+
118
+ // 2. Проверка значения: `$direction` должен быть `'start'`
119
+ // или `'end'`.
120
+ // Используем функцию `list.index` для поиска значения в списке.
121
+ // Если `direction` не найден в списке `('start' 'end')`, выводим
122
+ // сообщение об ошибке значения. Важно: эта проверка выполняется
123
+ // только если первая проверка прошла (или пропущена).
124
+ @if not list.index('start' 'end', $direction) {
125
+ @debug log-invalid-value(
126
+ 'get-list-item',
127
+ $direction,
128
+ '$direction',
129
+ ('start', 'end')
130
+ );
131
+ } @else {
132
+
133
+ // Если обе проверки пройдены (или не выполнялись из-за
134
+ // логики условия), переходим к основной логике функции.
135
+
136
+ // СОЗДАНИЕ КАРТЫ (MAP) ДЛЯ ВЫБОРА НУЖНОЙ ФУНКЦИИ
137
+ // Карта связывает строковые ключи с результатами
138
+ // соответствующих функций. Это элегантная альтернатива
139
+ // конструкции if-else.
140
+ $-directions: (
141
+ 'start': get-list-item-start($list), // Вызываем функцию для получения первого элемента
142
+ 'end': get-list-item-end($list) // Вызываем функцию для получения последнего элемента
143
+ );
144
+
145
+ // ПОЛУЧЕНИЕ РЕЗУЛЬТАТА ИЗ КАРТЫ
146
+ // Используем функцию `map.get` для получения значения по
147
+ // ключу `$direction`:
148
+ // - Если `$direction = 'start'`, получим результат `get-list-item-start($list)`
149
+ // - Если `$direction = 'end'`, получим результат `get-list-item-end($list)`
150
+
151
+ // Альтернативный подход: использовать прямое условие:
152
+ // `if(sass($direction == "start"): get-list-item-start($list); else: get-list-item-end($list))`
153
+ // Но карта более масштабируема для добавления новых
154
+ // направлений.
155
+ $-result: map.get($-directions, $direction);
156
+
157
+ // Примечание: если бы у нас было больше вариантов, можно
158
+ // было бы добавить их в карту:
159
+ // - `'middle': get-list-item-middle($list),`
160
+ // - `'second': get-list-item-second($list),`
161
+ // и т.д.
162
+
163
+ }
164
+
165
+ // (!) Важно: мы не проводим проверку на тип `arglist` и/или
166
+ // `list`, поскольку эти операции уже реализованы в функциях
167
+ // `get-list-item-start` и `get-list-item-end`.
168
+
169
+ // ВОЗВРАТ РЕЗУЛЬТАТА
170
+ // - Если были ошибки валидации, вернется пустая строка
171
+ // (инициализированное значение)
172
+ // - Если валидация прошла, вернется результат соответствующей
173
+ // функции
174
+ // (!) Важно: функция `log-invalid-type` и `log-invalid-value`
175
+ // возвращают `null`, но здесь мы его не используем, поэтому
176
+ // ошибки только логируются, но не влияют на поток выполнения.
177
+ @return $-result;
178
+
179
+ }
@@ -0,0 +1,139 @@
1
+ @use 'sass:math';
2
+ @use '../../loggers/log-invalid-type' as *;
3
+ @use '../../validators/type-of/is-number' as *;
4
+
5
+ /// Вычисляет абсолютное значение по проценту от целого.
6
+ ///
7
+ /// Функция выполняет обратную операцию процентного расчета:
8
+ /// находит абсолютное числовое значение, которое составляет
9
+ /// указанный процент от заданного целого числа.
10
+ ///
11
+ /// Важные особенности функции:
12
+ /// - Преобразует процентное значение в абсолютное число
13
+ /// - Корректно работает с процентными единицами измерения
14
+ /// - Использует безопасное деление через `math.div()`
15
+ /// - Возвращает значение в тех же единицах измерения, что и
16
+ /// `$whole`
17
+ /// - Идеально подходит для обратных расчетов от процентов к
18
+ /// числам
19
+ /// ---
20
+ /// @name get-number-from-percent
21
+ /// @group utilities-getters
22
+ /// @since 2025.12.27
23
+ /// @access public
24
+ /// @author Murad Rustamov (therteenten)
25
+ /// @link https://sourcecraft.dev/users/therteenten/overview SourceCraft - therteenten
26
+ /// @link https://sourcecraft.dev/omnisass/library SourceCraft - OmniSass
27
+ /// @link https://sass-lang.com/documentation/modules/math#div См. также: Официальная документация Sass - Функция math.div()
28
+ /// @link https://sass-lang.com/documentation/values/numbers#units См. также: Официальная документация Sass - Единицы измерения чисел
29
+ /// @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed MDN Web Docs - Number.toFixed()
30
+ /// @example scss - Базовые расчеты
31
+ /// @debug get-number-from-percent(50%, 200); // 100
32
+ /// @debug get-number-from-percent(25%, 1000); // 250
33
+ /// @debug get-number-from-percent(75%, 80); // 60
34
+ /// @debug get-number-from-percent(100%, 150); // 150
35
+ /// @example scss - Расчет с десятичными процентами
36
+ /// @debug get-number-from-percent(33.33%, 300); // 99.99
37
+ /// @debug get-number-from-percent(12.5%, 800); // 100
38
+ /// @debug get-number-from-percent(0.1%, 1000); // 1
39
+ /// @debug get-number-from-percent(150%, 200); // 300
40
+ /// @example scss - Расчет с единицами измерения
41
+ /// @debug get-number-from-percent(50%, 200px); // 100px
42
+ /// @debug get-number-from-percent(25%, 4rem); // 1rem
43
+ /// @debug get-number-from-percent(10%, 2em); // 0.2em
44
+ /// @debug get-number-from-percent(33%, 150%); // 49.5%
45
+ /// @example scss - Практическое использование для адаптивных отступов
46
+ /// $container-width: 1200px;
47
+ /// $gutter-percentage: 5%;
48
+ /// $gutter-width: get-number-from-percent($gutter-percentage, $container-width);
49
+ /// // $gutter-width: 60px
50
+ /// .container {
51
+ /// width: $container-width;
52
+ /// padding-left: $gutter-width;
53
+ /// padding-right: $gutter-width;
54
+ /// }
55
+ /// @example css - Результат
56
+ /// .container {
57
+ /// width: 1200px;
58
+ /// padding-left: 60px;
59
+ /// padding-right: 60px;
60
+ /// }
61
+ /// @example scss - Практическое использование для типографики
62
+ /// $base-font-size: 16px;
63
+ /// $line-height-percentage: 150%;
64
+ /// $line-height: get-number-from-percent($line-height-percentage, $base-font-size);
65
+ /// // $line-height: 24px
66
+ /// body {
67
+ /// font-size: $base-font-size;
68
+ /// line-height: $line-height;
69
+ /// }
70
+ /// @example css - Результат
71
+ /// body {
72
+ /// font-size: 16px;
73
+ /// line-height: 24px;
74
+ /// }
75
+ /// @example scss - Практическое использование для скидок
76
+ /// $original-price: 5000;
77
+ /// $discount-percent: 20%;
78
+ /// $discount-amount: get-number-from-percent($discount-percent, $original-price);
79
+ /// // $discount-amount: 1000
80
+ /// $final-price: $original-price - $discount-amount;
81
+ /// // $final-price: 4000
82
+ /// .price::after {
83
+ /// content: "#{$final-price} руб.";
84
+ /// }
85
+ /// @example css - Результат
86
+ /// .price::after {
87
+ /// content: "4000 руб.";
88
+ /// }
89
+ /// @param {Number} $percentage - Процентное значение, которое
90
+ /// нужно преобразовать в абсолютное число. Должно содержать
91
+ /// единицу измерения '%' (например, "50%", "25.5%", "100%").
92
+ /// @param {Number} $whole - Целое число, от которого вычисляется
93
+ /// процент. Может быть любым числом (целым, дробным, с единицами
94
+ /// измерения или без).
95
+ /// @return {Number} - Абсолютное числовое значение, представляющее
96
+ /// указанный процент от целого. Возвращает значение в тех же
97
+ /// единицах измерения, что и параметр `$whole`.
98
+ /// @throws {Error} - Может выбросить ошибку если `$percentage`
99
+ /// не содержит единицы измерения '%' или если параметры
100
+ /// не являются числами.
101
+ @function get-number-from-percent($percentage, $whole) {
102
+
103
+ // ВАЛИДАЦИЯ ВХОДНЫХ ПАРАМЕТРОВ
104
+ // Проверяем, что `$percentage` является числом. Используем
105
+ // вспомогательную функцию `is-number` для проверки типа
106
+ @if not is-number($percentage) {
107
+
108
+ // Если `$percentage` не число, логируем ошибку типа.
109
+ // `log-invalid-type` выводит информативное сообщение об ошибке
110
+ @return log-invalid-type(
111
+ 'get-number-from-percent',
112
+ $percentage,
113
+ '$percentage',
114
+ 'number'
115
+ );
116
+
117
+ } @else if not is-number($whole) {
118
+
119
+ // Проверяем, что `$whole` является числом.
120
+ // Эта проверка выполняется только если первая проверка
121
+ // пройдена. Если `$percentage` не число, мы сюда не
122
+ // попадем из-за `@else if`
123
+ @return log-invalid-type(
124
+ 'get-number-from-percent',
125
+ $whole,
126
+ '$whole',
127
+ 'number'
128
+ );
129
+
130
+ } @else {
131
+
132
+ // ОСНОВНАЯ ЛОГИКА ФУНКЦИИ
133
+ // Оба параметра прошли валидацию
134
+ // Вычисляем результат: (процент / 100%) * целое
135
+ @return math.div($percentage, 100%) * $whole;
136
+
137
+ }
138
+
139
+ }
@@ -0,0 +1,199 @@
1
+ @use 'sass:math';
2
+ @use '../../loggers/log-invalid-type' as *;
3
+ @use '../../validators/type-of/is-number' as *;
4
+
5
+ /// Вычисляет высоту на основе ширины и соотношения сторон.
6
+ ///
7
+ /// Функция рассчитывает высоту элемента по заданной ширине
8
+ /// и соотношению сторон (aspect ratio). Соотношение сторон
9
+ /// определяется как `ширина / высота`. Это фундаментальная
10
+ /// операция в веб-дизайне, используемая для создания
11
+ /// адаптивных медиа-элементов, изображений, видео-контейнеров
12
+ /// и поддержания пропорций элементов.
13
+ ///
14
+ /// Математическая формула:
15
+ /// - `height = width / ratio` (где `ratio = width / height`)
16
+ ///
17
+ /// Свойства результата:
18
+ /// - При `ratio = 1` (квадрат) → высота равна ширине
19
+ /// - При `ratio > 1` (альбомная ориентация) → высота меньше
20
+ /// ширины
21
+ /// - При `ratio < 1` (портретная ориентация) → высота больше
22
+ /// ширины
23
+ /// - Результат имеет те же единицы измерения, что и `$width`
24
+ /// - Функция сохраняет пропорции исходного соотношения сторон
25
+ ///
26
+ /// Важные особенности функции:
27
+ /// - Вычисляет высоту по ширине и соотношению сторон
28
+ /// - Использует `math.div()` для безопасного деления
29
+ /// - Сохраняет единицы измерения ширины (`px`, `rem`, `em`,
30
+ /// `%`, и т.д.)
31
+ /// - Поддерживает дробные значения соотношения сторон
32
+ /// - Идеально подходит для адаптивных вычислений в CSS
33
+ /// - Является основой для поддержания пропорций в веб-дизайне
34
+ ///
35
+ /// > Вычисление высоты по соотношению сторон является ключевой
36
+ /// > техникой в адаптивном веб-дизайне. Этот подход позволяет
37
+ /// > создавать элементы с фиксированными пропорциями, которые
38
+ /// > корректно масштабируются на различных устройствах и размерах
39
+ /// > экрана. Особенно полезно для видео-контейнеров, изображений
40
+ /// > и адаптивных iframe.
41
+ /// >
42
+ /// > Пример: для отображения видео 16:9 с шириной 800px,
43
+ /// > высота будет вычислена как 800 / (16/9) = 450px.
44
+ /// ---
45
+ /// @name get-number-height-by-ratio
46
+ /// @group utilities-getters
47
+ /// @since 2025.12.27
48
+ /// @access public
49
+ /// @author Murad Rustamov (therteenten)
50
+ /// @link https://sourcecraft.dev/users/therteenten/overview SourceCraft - therteenten
51
+ /// @link https://sourcecraft.dev/omnisass/library SourceCraft - OmniSass
52
+ /// @link https://sass-lang.com/documentation/values/numbers См. также: Официальная документация Sass - Тип данных "Числа"
53
+ /// @link https://sass-lang.com/documentation/modules/math См. также: Официальная документация Sass - Модуль math
54
+ /// @link https://sass-lang.com/documentation/modules/math#div См. также: Официальная документация Sass - Функция math.div()
55
+ /// @link https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio См. также: MDN Web Docs - CSS свойство aspect-ratio
56
+ /// @link https://css-tricks.com/aspect-ratio-boxes/ См. также: CSS-Tricks - Блоки с фиксированным соотношением сторон
57
+ /// @link https://www.w3schools.com/howto/howto_css_aspect_ratio.asp См. также: W3Schools - Как создавать блоки с фиксированным соотношением сторон
58
+ /// @example scss - Стандартные соотношения сторон видео
59
+ /// @debug get-number-height-by-ratio(800px, math.div(16, 9)); // 450px
60
+ /// @debug get-number-height-by-ratio(800px, 1.7777777778); // 449.999999994375px
61
+ /// @debug get-number-height-by-ratio(800px, math.div(4, 3)); // 600px
62
+ /// @debug get-number-height-by-ratio(800px, 1.3333333333); // 600.0000000150001px
63
+ /// @debug get-number-height-by-ratio(800px, math.div(21, 9)); // 342.85714285714283px
64
+ /// @debug get-number-height-by-ratio(800px, 2.3333333333); // 342.8571428620408px
65
+ /// @example scss - Квадратные и прямоугольные элементы
66
+ /// @debug get-number-height-by-ratio(400px, 1); // 400px (квадрат)
67
+ /// @debug get-number-height-by-ratio(600px, 2); // 300px (горизонтальный прямоугольник 2:1)
68
+ /// @debug get-number-height-by-ratio(600px, 0.5); // 1200px (вертикальный прямоугольник 1:2)
69
+ /// @debug get-number-height-by-ratio(300px, math.div(3, 2)); // 200px (3:2)
70
+ /// @debug get-number-height-by-ratio(300px, math.div(2, 3)); // 450px (2:3)
71
+ /// @example scss - Разные единицы измерения
72
+ /// @debug get-number-height-by-ratio(100%, math.div(16, 9)); // 56.25%
73
+ /// @debug get-number-height-by-ratio(50rem, math.div(16, 9)); // 28.125rem
74
+ /// @debug get-number-height-by-ratio(80vw, math.div(16, 9)); // 45vw
75
+ /// @debug get-number-height-by-ratio(1200px, math.div(16, 9)); // 675px
76
+ /// @debug get-number-height-by-ratio(64em, math.div(4, 3)); // 48em
77
+ /// @example scss - Дробные значения ширины
78
+ /// @debug get-number-height-by-ratio(750.5px, math.div(16, 9)); // 422.15625px
79
+ /// @debug get-number-height-by-ratio(1024.75px, 1.5); // 683.1666666666666px
80
+ /// @debug get-number-height-by-ratio(256.25rem, math.div(5, 4)); // 205rem
81
+ /// @debug get-number-height-by-ratio(99.9%, 1.618); // 61.74289245982695%
82
+ /// @example scss - Популярные соотношения сторон
83
+ /// // 1:1 - Квадрат, Instagram фото
84
+ /// @debug get-number-height-by-ratio(500px, 1); // 500px
85
+ ///
86
+ /// // 4:3 - Стандартный монитор, некоторые планшеты
87
+ /// @debug get-number-height-by-ratio(1024px, math.div(4, 3)); // 768px
88
+ ///
89
+ /// // 16:9 - Современное видео, Full HD
90
+ /// @debug get-number-height-by-ratio(1920px, math.div(16, 9)); // 1080px
91
+ ///
92
+ /// // 21:9 - Ультраширокий монитор, кинематографичный формат
93
+ /// @debug get-number-height-by-ratio(2560px, math.div(21, 9)); // 1097.142857142857px
94
+ ///
95
+ /// // 3:2 - Некоторые фотоаппараты, MacBook
96
+ /// @debug get-number-height-by-ratio(1800px, math.div(3, 2)); // 1200px
97
+ ///
98
+ /// // 1.618:1 - Золотое сечение
99
+ /// @debug get-number-height-by-ratio(1000px, 1.618); // 618.0469715698392px
100
+ /// @example scss - Для адаптивных контейнеров
101
+ /// .video-container {
102
+ /// width: 100%;
103
+ /// height: get-number-height-by-ratio(100%, math.div(16, 9));
104
+ /// }
105
+ ///
106
+ /// .square-image {
107
+ /// width: 300px;
108
+ /// height: get-number-height-by-ratio(300px, 1);
109
+ /// }
110
+ ///
111
+ /// .portrait-card {
112
+ /// width: 250px;
113
+ /// height: get-number-height-by-ratio(250px, math.div(3, 4));
114
+ /// }
115
+ /// @example css - Результат
116
+ /// .video-container {
117
+ /// width: 100%;
118
+ /// height: 56.25%;
119
+ /// }
120
+ ///
121
+ /// .square-image {
122
+ /// width: 300px;
123
+ /// height: 300px;
124
+ /// }
125
+ ///
126
+ /// .portrait-card {
127
+ /// width: 250px;
128
+ /// height: 333.3333333333px;
129
+ /// }
130
+ /// @example scss - Проверка граничных значений
131
+ /// @debug get-number-height-by-ratio(0px, math.div(16, 9)); // 0px
132
+ /// @debug get-number-height-by-ratio(1000px, math.div(1, 0)); // 0px
133
+ /// @debug get-number-height-by-ratio(1000px, 0); // Ошибка: деление на ноль (calc(infinity * 1px))
134
+ /// @debug get-number-height-by-ratio(1000px, math.div(0, 1)); // Ошибка: деление на ноль (calc(infinity * 1px))
135
+ /// @example scss - Очень большие соотношения
136
+ /// @debug get-number-height-by-ratio(1000px, 10); // 100px (очень широкий)
137
+ /// @debug get-number-height-by-ratio(1000px, 0.1); // 10000px (очень узкий)
138
+ /// @debug get-number-height-by-ratio(500px, 100); // 5px
139
+ /// @debug get-number-height-by-ratio(500px, 0.01); // 50000px
140
+ /// @param {Number} $width - Ширина элемента. Может быть
141
+ /// любым числом с единицами измерения (`px`, `rem`, `em`,
142
+ /// `%`, `vw`, и т.д.) или без них.
143
+ /// @param {Number} $ratio - Соотношение сторон, вычисляемое
144
+ /// как `ширина / высота`. Например:
145
+ /// - 1.7777777778 для 16:9
146
+ /// - 1.3333333333 для 4:3
147
+ /// - 1 для квадрата
148
+ /// - 0.75 для портретного формата 3:4
149
+ /// @return {Number} - Высота элемента, рассчитанная по формуле
150
+ /// `height = width / ratio`. Сохраняет единицы измерения
151
+ /// параметра `$width`.
152
+ /// @throws {Error} - Выбрасывает ошибку деления на ноль, если
153
+ /// `$ratio = 0`. Это соответствует математически невозможной
154
+ /// ситуации, когда высота была бы бесконечной.
155
+ @function get-number-height-by-ratio($width, $ratio) {
156
+
157
+ @if not is-number($width) {
158
+
159
+ // Логируем ошибку: неверный тип параметра $width
160
+ @return log-invalid-type(
161
+ 'get-number-height-by-ratio',
162
+ $width,
163
+ '$width',
164
+ 'number'
165
+ );
166
+
167
+ } @else if not is-number($ratio) {
168
+
169
+ // Логируем ошибку: неверный тип параметра $ratio
170
+ @return log-invalid-type(
171
+ 'get-number-height-by-ratio',
172
+ $ratio,
173
+ '$ratio',
174
+ 'number'
175
+ );
176
+
177
+ } @else {
178
+
179
+ // Оба параметра корректны, вычисляем высоту
180
+ // Используется функция math.div для деления ширины
181
+ // на соотношение (более безопасная альтернатива
182
+ // обычному оператору / в Sass)
183
+ @return math.div($width, $ratio);
184
+
185
+ }
186
+
187
+ }
188
+
189
+ /// @name get-height-by-ratio
190
+ /// @alias get-number-height-by-ratio
191
+ /// @group utilities-aliases
192
+ /// @since 2025.12.27
193
+ /// @access public
194
+ /// @author Murad Rustamov (therteenten)
195
+ /// @link https://sourcecraft.dev/users/therteenten/overview SourceCraft - therteenten
196
+ /// @link https://sourcecraft.dev/omnisass/library SourceCraft - OmniSass
197
+ @function get-height-by-ratio($width, $ratio) {
198
+ @return get-number-height-by-ratio($width, $ratio);
199
+ }