Карты хороши, но карты не так просто отлаживать. Когда у вас есть простые карты, обычно довольно легко понять, что происходит, но когда вы работаете с огромными и / или вложенными, возможно динамически обновляемыми картами, может быть трудно отслеживать, что происходит.
… и вдруг в вашем коде появляется ошибка. Взламывая сайт, вы как-то разрабатываете.
Не бойтесь моих друзей, у меня есть возможное решение.
Как насчет inspect()
@debug
На днях веб-разработчик Стюарт Транн спросил, как мы можем отладить карту, чтобы увидеть, как она выглядит.
Первое, что мне пришло в голову, была функция inspect()
Эта функция была добавлена в то же самое время, когда карты вышли, чтобы проверить содержание карты.
Возможно, вы заметили, что если вы попытаетесь отобразить карту в виде значения CSS, вы получите следующее сообщение:
(sass: map) не является допустимым значением CSS.
Dang. Вот почему функция inspect()
Таким образом, вы можете увидеть что-то вроде:
test {
inspect: (sass: map);
}
Проблема с inspect()
Можно подумать о @debug
Время строить то, что помогает нам, ребята.
Смешай все вещи!
Что если бы мы использовали тот факт, что CSS довольно аккуратен, когда дело доходит до отображения пар ключ / значение? Мы могли бы зациклить на карте и отобразить ключ и значение в качестве объявления в фиктивном селекторе. Давай сделаем это!
/// Prints a map as a CSS rule
/// @param {Map} $map
@mixin debug-map($map) {
@at-root {
__properties__ {
@each $key, $value in $map {
#{$key}: $value;
}
}
}
}
Примечание: мы используем __properties__
__proto__
Неплохо. Теперь, что если у нас есть вложенная карта внутри этой? Sass потерпит неудачу на дисплее $value
Таким образом, мы могли бы либо придумать какую-то странную и сложную логику, либо мы могли бы сделать ее простой и использовать inspect()
/// Prints a map as a CSS rule
/// @param {Map} $map
@mixin debug-map($map) {
@at-root {
__properties__ {
@each $key, $value in $map {
#{$key}: inspect($value);
}
}
}
}
Таким образом, если мы встретим вложенную карту, она будет отображаться как любое другое значение. Если мы хотим отладить эту вложенную карту сейчас, мы должны напрямую использовать debug-map
Добавление дополнительной информации
Что, если мы решили добавить дополнительную информацию, такую как длина, глубина или строковое представление проверенной карты? Это может быть полезно, не так ли?
Для этого нам нужно немного подправить наш миксин. Вместо непосредственного вывода селектора, мы можем напечатать проприетарную @
@mixin debug-map($map) {
@at-root {
@debug-map {
__toString__: inspect($map);
__length__: length($map);
__keys__: map-keys($map);
__properties__ {
@each $key, $value in $map {
#{$key}: inspect($value);
}
}
}
}
}
Чтобы вычислить глубину, нам нужен дополнительный инструмент, так как для этого нет встроенной функции. Оказывается, я сделал такую функцию некоторое время назад, но никогда не писал об этом. Я думаю, пришло время!
/// Compute the maximum depth of a map
/// @param {Map} $map
/// @return {Number} max depth of `$map`
@function depth($map) {
$level: 1;
@each $key, $value in $map {
@if type-of($value) == "map" {
$level: max(depth($value) + 1, $level);
}
}
@return $level;
}
Это рекурсивная функция, перебирающая каждую пару ключ / значение с карты, пока не найдет карту, в этом случае она вызывает себя и так далее. Затем возвращается число: глубина карты. Давайте обновим наш debug-map
@mixin debug-map($map) {
@at-root {
@debug-map {
__toString__: inspect($map);
__length__: length($map);
__depth__: depth($map);
__keys__: map-keys($map);
__properties__ {
@each $key, $value in $map {
#{$key}: inspect($value);
}
}
}
}
}
Последнее добавление, которое я могу предложить, — это печать типа каждого значения с карты прямо перед соответствующим ключом. Это может быть удобно в некоторых случаях:
@mixin debug-map($map) {
@at-root {
@debug-map {
__toString__: inspect($map);
__length__: length($map);
__depth__: depth($map);
__keys__: map-keys($map);
__properties__ {
@each $key, $value in $map {
#{'(' + type-of($value) + ') ' + $key}: inspect($value);
}
}
}
}
}
Давайте попробуем это!
Давайте посмотрим на следующую карту для наших тестов:
$person: (
'name': 'Hugo Giraudel',
'location': 'France',
'age': 22,
'glasses': true,
'kids': null,
'skills': ('HTML', 'CSS', 'Sass', 'JavaScript'),
'languages': (
'French': 'native',
'English': 'fluent',
'Spanish': 'notions'
)
);
А теперь давайте отладим это!
@include debug-map($person);
После компиляции он даст такой результат:
@debug-map {
__toString__: ("name": "Hugo Giraudel", "location": "France", "age": 22, "glasses": true, "has-kids": false, "skills": ("HTML", "CSS", "Sass", "JavaScript"), "languages": (("French": "native", "English": "fluent", "Spanish": "notions")));
__length__: 7;
__depth__: 2;
__keys__: "name", "location", "age", "glasses", "has-kids", "skills", "languages";
__properties__ {
(string) name: "Hugo Giraudel";
(string) location: "France";
(number) age: 22;
(bool) glasses: true;
(null) kids: false;
(list) skills: "HTML", "CSS", "Sass", "JavaScript";
(map) languages: ("French": "native", "English": "fluent", "Spanish": "notions");
}
}
Последние мысли
Там вы идете, ребята. Я надеюсь, что это может пригодиться, если вы когда-нибудь будете бороться с картами. Не стесняйтесь улучшать или добавлять дополнительные функции в этот маленький миксин. Моя цель состояла в том, чтобы сделать его как можно более простым и не перегружать его слишком сильно. Даже глубина карты в большинстве случаев может показаться немного излишней, но вы знаете … Хорошее дополнение!