Parue le 7 mars 2014, la version 3.3 du préprocesseur Sass apporte son lot de nouveautés que je vous propose de découvrir dans une série de billets.

Pour nous mettre en jambe, attardons-nous sur les maps. Ce nouveau type de données vient s’ajouter aux types déjà existant, à avoir les chaînes de caractères (string), les valeurs numériques (number), les couleurs (color), les booléens (boolean) et les listes (list).

Une donnée de type map permet de structurer les données par couple clé / valeur, comme nous le faisons depuis des lustres avec les tableaux PHP ou encore les structures JSON.

Syntaxe d’une map

Une map a une syntaxe similaire à une donnée de type list, si ce n’est que chaque valeur est identifiée par une clé :

$map: (key1: value1, key2: value2, key3: value3);

Avantages du type de données map

Jusqu’à présent la manipulation de listes imbriquées était relativement verbeuse parce que, à juste titre, aucun mécanisme n’était disponible pour cibler rapidement une valeur. Ainsi, en présence de structures un peu complexes, nous devions conjuguer avec la fonction zip() et une série d’appels à la fonction nth() pour accéder à la valeur souhaitée. Il faut bien l’avouer, le code était difficile à lire.

Prenons pour exemple une version un peu modifiée du code que je donne en exemple dans le chapitre 3 du livre Sass et Compass avancé :

Play with this gist on SassMeister.

Nous pouvons émettre quelques critiques à ce code :

  • de nombreuses variables globales sont instanciées ;
  • l’utilisation de la fonction zip() n’est pas naturelle pour le profane ;
  • tous les accès aux propriétés se font à l’aide d’index numériques qu’il nous faut lire mentalement dans différentes variables pour retrouver nos petits.

En adaptant la liste $message-themes en une map, la définition de nos types de messages gagne en lisibilité :

Play with this gist on SassMeister.

La maintenance de ce code paraît bien plus facile, n’est-ce pas ?
Quelques précisions peuvent toutefois y être apportés :

  1. À chaque itération de la boucle @each, la variable $msg est instanciée par une liste de deux membres : la clé et la valeur courante. Ainsi, lors de la première itération $msg vaut status (background: #d5edf8, border: #92cae4, color: #205791) ; soit le type de message et une nouvelle map qui stocke ses propriétés.
  2. Les fonctions de manipulation des listes comme nth() fonctionnent sur les maps.
  3. Sass 3.3 ne génère plus une erreur lorsqu’il rencontre une virgule après le dernier membre d’une liste (oh yeah \m/).
  4. Comme nous le verrons plus loin, de nouvelles fonctions telle que map-get() ont fait leur apparition. Cette dernière retourne la valeur associée à la clé (second argument) dans une map (premier argument).

Boucle @each à assignation multiple

Introduire le type de données map c’est bien. Éviter de devoir recourir aux artifices nth($var, 1) et nth($var, 2) pour accéder à la clé et sa valeur, c’est encore mieux.
C’est dans ce but que la directive @each a évolué pour instancier la clé et sa valeur à chaque itération. En présence d’une map, la syntaxe de la boucle peut devenir :

@each $key, $value in $map {
  // votre code
}

J’emploie le conditionnel parce qu’il est toujours possible d’instancier une seule variable avec les valeurs uniquement.
Ainsi, l’exemple précédent se simplifie drastiquement (je remplace tout de même border par border-color) :

Play with this gist on SassMeister.

Fonctions de manipulation des maps

L’introduction de ce nouveau type de données s’accompagne par l’ajout de 6 nouvelles fonctions de manipulation des maps :

  1. map-get($map, $key) : retourne la valeur dans la $map ayant pour clé $key. La valeur null est retournée en l’absence de valeur.
  2. map-merge($map1, $map2) : retourne le résultat de la fusion de deux maps $map1 et $map2. En cas de conflit, c’est à dire si une clé existe dans les deux maps, la seconde map est prioritaire. En sommes, pour une même clé la valeur de la seconde map écrasera celle de la première.
  3. map-remove($map, $key) : retourne une nouvelle map dont la clé $key est supprimée.
  4. map-keys($map) : retourne une liste des clés de $map, séparées par des virgules.
  5. map-values($map) : retourne une liste des valeurs de $map, séparées par des virgules.
  6. map-has-key($map, $key) : teste l’existence de la clé $key dans $map.

Les noms et les finalités de ces fonctions sont assez explicites pour nous dispenser d’exemple d’utilisation. Je vais cependant m’attarder un peu sur la fonction map-merge() qui ouvre de nouvelles perspectives dans la conception d’un projet et plus particulièrement dans la gestion des variables par défaut.

Fusionner deux maps

La fonction map-merge() est intéressante parce qu’elle offre un moyen d’étendre une map facilement. Couplée au mécanisme de déclaration de variable par défaut, il est possible d’élaborer un système d’enrichissement et de surcharge de styles en un tour de main.

Dans l’exemple qui suit, nous supposons que les codes de styles.scss et _messages.scss existent dans deux fichiers distincts. Le second étant importé par le premier :

Play with this gist on SassMeister.

En plus d’étendre la map $message-themes du type de message de succès ok, la valeur de sa clé warning est surchargée. Sass 3.3 nous permet de totalement repenser la déclaration de nos variables par défaut !

Des maps en argument multiple

À l’instar des listes, les maps peuvent être passées à des fonctions et mixins comme une liste d’argument en suffixant la variable par trois points .... Par exemple, si vous utilisez Compass, vous pouvez écrire :

Play with this gist on SassMeister.

Si vous souhaitez appeler une fonction ou un mixin à l’aide d’une liste et d’une map, il suffit de placer la liste en premier puis la map comme dans mafonction($list..., $map...).

À lire
Si la notion d’argument multiple vous est étrangère ou un temps soit peu cryptique, je vous invite à lire le chapitre 2 du livre Sass et Compass avancé ;-)

Enfin, la nouvelle fonction keywords($args) permet de créer une map depuis un argument multiple passé à une fonction ou un mixin. Voici par exemple comment pourrait être réécrit le mixin link-colors de Compass :

Play with this gist on SassMeister.

Pour conclure

L’ajout des maps va indéniablement marquer une nouvelle évolution dans nos manières d’aborder des problématiques d’organisation de nos projets Sass. Les perspectives offertes par le couple !default / map-merge() sont énormes. De quoi nous donner envie de gérer du multi-thème dans nos projets :)

publicité (chargement)

3 réponses pour Sass 3.3 : le nouveau type de données Maps

  1. wsu dit :

    Bonjour, pour commencer, merci pour votre article… Pour ma part j’ai a la fin de cet article voulu tenter l’aventure, j’ai donc installer sass 3.3.3 mais je n’ai pas pu aller plus loin, j’utilise aussi compass, fmk dont je ne souhaite pas me séparer et je viens de passer deux jours a comprendre qu’a première vu et si je ne me trompe pas, compass 0.12.1 et 0.12.3 ne serrait pour le moment compatible qu’avec sass 3.2.14, comme j’ai vu des articles au sujet de compass sur votre site, je me demande si vous n’auriez pas par hasard des infos a ce sujet. Merci d’avance !

  2. piouPiouM dit :

    Bonjour wsu,

    Il vous faut utiliser Bundler que j’aborde dans le billet Gestion avancée de Sass et Compass avec RVM et Bundler. Je viens par ailleurs de l’éditer pour ajouter un disclamer : la couche RVM n’est pas utile.

    Puisque vous venez d’installer Sass 3.3.3 de manière globale à votre système et que, j’imagine, que vous ne souhaitez pas forcément migrer de suite tous vos projets sur Bundler, le plus simple à faire est :

    1. De désinstaller cette version de Sass : gem uninstall sass --version 3.3.3.
    2. D’installer Bundler globalement : gem install bundler.
    3. À la racine de votre projet de test créer un fichier Gemfile et le renseigner correctement (se référer au billet précédemment cité ou au chapitre 6 de mon livre).
    4. Tout en restant à la racine du projet, installer localement les gems (dont Sass) à l’aide de Bundler : bundler install --path .vendors/bundler

    Cela étant fait, il vous suffira de lancer la commande bundle sass pour utiliser la dernière version de Sass dans ce projet, sans impacter les autres.

  3. wsu dit :

    Un grand merci pour cette réponse, cependant, je rencontre certains problèmes, pour commencer je suis sous win64 et voici certaines infos:

    C:\>ruby -v
    ruby 2.0.0p451 (2014-02-24) [x64-mingw32]
    C:\>sass -v
    Sass 3.2.14 (Media Mark)
    C:\>compass -v
    Compass 0.12.2 (Alnilam)
    Copyright (c) 2008-2014 Chris Eppstein
    Released under the MIT License.
    Compass is charityware.
    Please make a tax deductable donation for a worthy cause: http://umdf.org/compass

    A partir de la, j’ai donc fait:

    1. gem install bundle (mais pas bundler)
    2. J’ai ajouter “wamp/www/test/Gemfile” contenant ceci:
          source: rubygems
          gem "compass", "~> 0.12.2"
          gem "oily_png"
      la j’ai eu un soucis, c’est quoi ce Gemfile, quel est son extension ? pour le coup, je n’en ai pas mis !
    3. c:\wamp/www/test> bundle install —path .vendors/bundle (encore avec bundle et pas bundler)

    Suite a tous ça, 2 dossiers (.bundle et .vendors) se sont créer mais pas le Gemfile.lock J’ai quand même continuer avec : c:\>bundle sass qui me retourne un soucis: DL is deprecated, please use Fiddle

    J’ai cherché des choses a ce sujet mais je n’ai rien trouvé en rapport avec compass et je ne connais pas ruby, je sollicite donc une nouvelle fois votre aide !!!

    Merci encore !

Ajouter un commentaire


Syndication

Réseaux sociaux