
Il s'agit de la deuxième partie de l'article sur la création d'un outil capable d'exporter toutes les icônes placées dans un fichier Sketch: dans différents formats, pour différentes plateformes, avec la possibilité de tester A / B de chaque icône.
Vous pouvez lire la première partie
du lien .

La dernière fois, nous avons préparé des fichiers Sketch contenant toutes les icônes dans les bons styles et avec les noms corrects. C'est au tour d'écrire du code.
Il suffit de dire que nous avons fait des essais et des erreurs. Après que notre chef d'équipe
Nihil Verma , qui a jeté les bases du script, ait développé le code source clé, j'ai commencé un processus qui a nécessité au moins trois phases de refactoring et de nombreuses modifications. Pour cette raison, je n'entrerai pas dans les détails de la création du script et ne me concentrerai pas sur la façon dont il fonctionne aujourd'hui, dans sa forme finale.
Créer un script
Le script de construction écrit sur Node.js est assez simple dans son travail: en important des dépendances, en déclarant une liste de fichiers Sketch à traiter (c'est une liste de marques, chacune ayant une liste de fichiers associés) et en s'assurant que Sketch est installé sur le client , le script traite les marques à tour de rôle, effectuant une série d'actions avec chacune d'elles.
- Prend des jetons de conception appropriés pour les marques (nous avons besoin de valeurs de couleur).
- Clone les fichiers Sketch associés à la marque, les décompresse pour extraire les fichiers JSON internes et traite certaines de leurs valeurs internes (plus d'informations plus loin).
- Lit les métadonnées nécessaires à partir de ces fichiers JSON ( document.json , meta.json et pages / pageUniqueID.json ). Nous sommes intéressés par les listes de styles courants et de ressources / icônes contenues dans les fichiers.
- Après quelques manipulations supplémentaires avec les fichiers JSON, il recrée l'archive et, à l'aide de fichiers Sketch (clonés et mis à jour), exporte et crée les fichiers de sortie finaux pour trois plates-formes (iOS, Android, Web mobile).
Les parties pertinentes du script de construction peuvent être trouvées ici:
// ... modules imports here const SKETCH_FILES = { badoo: ['icons_common'], blendr: ['icons_common', 'icons_blendr'], fiesta: ['icons_common', 'icons_fiesta'], hotornot: ['icons_common', 'icons_hotornot'], }; const SKETCH_FOLDER_PATH = path.resolve(__dirname, '../src/'); const SKETCH_TEMP_PATH = path.resolve(SKETCH_FOLDER_PATH, 'tmp'); const DESTINATION_PATH = path.resolve(__dirname, '../dist'); console.log('Build started...'); if (sketchtool.check()) { console.log(`Processing Sketch file via ${sketchtool.version()}`); build(); } else { console.info('You need Sketch installed to run this script'); process.exit(1); } // ---------------------------------------- function build() { // be sure to start with a blank slate del.sync([SKETCH_TEMP_PATH, DESTINATION_PATH]); // process all the brands declared in the list of Sketch files Object.keys(SKETCH_FILES).forEach(async (brand) => { // get the design tokens for the brand const brandTokens = getDesignTokens(brand); // prepare the Sketch files (unzipped) and get a list of them const sketchUnzipFolders = await prepareSketchFiles({ brand, sketchFileNames: SKETCH_FILES[brand], sketchFolder: SKETCH_FOLDER_PATH, sketchTempFolder: SKETCH_TEMP_PATH }); // get the Sketch metadata const sketchMetadata = getSketchMetadata(sketchUnzipFolders); const sketchDataSharedStyles = sketchMetadata.sharedStyles; const sketchDataAssets = sketchMetadata.assetsMetadata; generateAssetsPDF({ platform: 'ios', brand, brandTokens, sketchDataSharedStyles, sketchDataAssets }); generateAssetsSVGDynamicMobileWeb({ platform: 'mw', brand, brandTokens, sketchDataSharedStyles, sketchDataAssets }); generateAssetsVectorDrawableDynamicAndroid({ platform: 'android', brand, brandTokens, sketchDataSharedStyles, sketchDataAssets }); }); }
En fait, le code du pipeline est beaucoup plus compliqué. La raison de cette complexité réside dans les fonctions
prepareSketchFiles
,
getSketchMetadata
et
generateAssets[format][platform]
. Ci-dessous, je vais essayer de les décrire plus en détail.
Préparation des fichiers d'esquisse
La première étape du processus d'assemblage est la préparation des fichiers Sketch, qui seront ensuite utilisés pour exporter des ressources pour différentes plates-formes.
Les fichiers associés à une marque particulière (par exemple, dans le cas de Blendr, il s'agit des
fichiers icons_common.sketch et
icons_blendr.sketch ) sont clonés dans un dossier temporaire (plus précisément, dans un sous-dossier nommé d'après la marque en cours de traitement) et décompressé.
Ensuite, les fichiers JSON sont traités. Un préfixe est ajouté au nom des ressources soumises aux tests A / B - ainsi, lors de l'exportation, elles seront enregistrées dans un sous-dossier avec un nom prédéfini (correspondant au nom unique de l'expérience). Vous pouvez comprendre si une ressource est soumise à un test A / B par le nom de la page sur laquelle elle est stockée: si c'est le cas, le nom contiendra le préfixe "
XP_ ".

Dans l'exemple ci-dessus, les ressources exportées seront stockées dans un sous-dossier de «
this__is_an_experiment » avec un nom de fichier de la forme «
nom-icône [nom-variante] .ext ».
Lecture des métadonnées d'un croquis
La deuxième étape importante consiste à extraire toutes les métadonnées nécessaires des fichiers Sketch, ou plutôt des fichiers JSON internes. Comme nous l'avons vu ci-dessus, ce sont deux fichiers principaux (
document.json et
meta.json ) et des fichiers de page (
pages / pageUniqueId.json ).
Le fichier
document.json est utilisé pour obtenir la liste des styles courants qui apparaît sous la propriété de l'objet
layerStyles :
{ "_class": "document", "do_objectID": "45D2DA82-B3F4-49D1-A886-9530678D71DC", "colorSpace": 1, ... "layerStyles": { "_class": "sharedStyleContainer", "objects": [ { "_class": "sharedStyle", "do_objectID": "9BC39AAD-CDE6-4698-8EA5-689C3C942DB4", "name": "features/feature-like", "value": { "_class": "style", "fills": [ { "_class": "fill", "isEnabled": true, "color": { "_class": "color", "alpha": 1, "blue": 0.10588235408067703, "green": 0.4000000059604645, "red": 1 }, "fillType": 0, "noiseIndex": 0, "noiseIntensity": 0, "patternFillType": 1, "patternTileScale": 1 } ], "blur": {...}, "startMarkerType": 0, "endMarkerType": 0, "miterLimit": 10, "windingRule": 1 } }, ...
Nous stockons des informations de base sur chaque style dans un objet au format clé-valeur. Il sera utilisé plus tard lorsque nous aurons besoin d'extraire le nom du style sur la base d'un ID unique (propriété
do_objectID
dans Sketch):
const parsedSharedStyles = {}; parsedDocument.layerStyles.objects.forEach((object) => { parsedSharedStyles[object.do_objectID] = { name: object.name, isFill: _.get(object, 'value.fills[0].color') !== undefined, isBorder: _.get(object, 'value.borders[0].color') !== undefined, }; });
Maintenant, nous allons dans le fichier
meta.json et obtenons une liste de pages. Nous sommes intéressés par leur
unique-id
et leur
name
:
{ "commit": "623a23f2c4848acdbb1a38c2689e571eb73eb823", "pagesAndArtboards": { "EE6BE8D9-9FAD-4976-B0D8-AB33D2B5DBB7": { "name": "Icons", "artboards": { "3275987C-CE1B-4369-B789-06366EDA4C98": { "name": "badge-feature-like" }, "C6992142-8439-45E7-A346-FC35FA01440F": { "name": "badge-feature-crush" }, ... "7F58A1C4-D624-40E3-A8C6-6AF15FD0C32D": { "name": "tabbar-livestream" } ... } }, "ACF82F4E-4B92-4BE1-A31C-DDEB2E54D761": { "name": "XP_this__is_an_experiment", "artboards": { "31A812E8-D960-499F-A10F-C2006DDAEB65": { "name": "this__is_an_experiment/tabbar-livestream[variant1]" }, "20F03053-ED77-486B-9770-32E6BA73A0B8": { "name": "this__is_an_experiment/tabbar-livestream[variant2]" }, "801E65A4-3CC6-411B-B097-B1DBD33EC6CC": { "name": "this__is_an_experiment/tabbar-livestream[control]" } } },
Ensuite, nous lisons les fichiers JSON correspondant Ă chaque page du dossier
pages (je répète que les noms de fichiers sont au
format [pageUniqueId] .json ) et étudions les ressources stockées sur cette page (elles ressemblent à des calques). Ainsi, nous obtenons le
nom , la
largeur / hauteur de chaque icĂ´ne, les
métadonnées Sketch pour l'icône de cette couche, et si nous avons affaire à une page d'
expérimentation , alors le nom du
test A / B et une
variante de cette icĂ´ne.
Remarque : l'objet page.json a un périphérique très complexe, donc je ne m'attarderai pas dessus. Si vous êtes intéressé par ce qu'il y a à l'intérieur, je vous conseille de créer un nouveau fichier Sketch vide, d'y ajouter du contenu et de l'enregistrer; puis renommez son extension en ZIP, décompressez-la et examinez l'un des fichiers du dossier pages.
Dans le processus de traitement des plans de travail, nous créerons également une
liste d'expériences (et de ressources connexes). Nous en aurons besoin pour déterminer quelles variations de l'icône sont utilisées dans quelle expérience - les noms des variations de l'icône sont attachés à l'objet «de base».
Pour chaque fichier Sketch
assetsMetadata
marque en cours de traitement, nous créons un objet
assetsMetadata
qui ressemble Ă ceci:
{ "navigation-bar-edit": { "do_objectID": "86321895-37CE-4B3B-9AA6-6838BEDB0977", ...sketch_artboard_properties, "name": "navigation-bar-edit", "assetname": "navigation-bar-edit", "source": "icons_common", "width": 48, "height": 48 "layers": [ { "do_objectID": "A15FA03C-DEA6-4732-9F85-CA0412A57DF4", "name": "Path", ...sketch_layer_properties, "sharedStyleID": "6A3C0FEE-C8A3-4629-AC48-4FC6005796F5", "style": { ... "fills": [ { "_class": "fill", "isEnabled": true, "color": { "_class": "color", "alpha": 1, "blue": 0.8784313725490196, "green": 0.8784313725490196, "red": 0.8784313725490196 }, } ], "miterLimit": 10, "startMarkerType": 0, "windingRule": 1 }, }, ], ... }, "experiment-name/navigation-bar-edit[variant]": { "do_objectID": "00C0A829-D8ED-4E62-8346-E7EFBC04A7C7", ...sketch_artboard_properties, "name": "experiment-name/navigation-bar-edit[variant]", "assetname": "navigation-bar-edit", "source": "icons_common", "width": 48, "height": 48 ...
Comme vous pouvez le voir, dans l'expérience, une seule icône (dans ce cas,
navigation-bar-edit ) peut correspondre à de nombreuses ressources. Dans le même temps, la même icône peut apparaître sous le même nom dans un autre fichier Sketch associé à la marque.
C'est très utile : nous utilisons cette astuce pour compiler un ensemble commun d'icônes, puis identifier des options spécifiques en fonction de la marque. C'est pourquoi nous avons déclaré les fichiers Sketch associés à une marque particulière en tant que tableau:
const SKETCH_FILES = { badoo: ['icons_common'], blendr: ['icons_common', 'icons_blendr'], fiesta: ['icons_common', 'icons_fiesta'], hotornot: ['icons_common', 'icons_hotornot'], };
Dans ce cas, l'ordre est d'une importance fondamentale. En fait, dans la fonction
getSketchMetadata
appelée par le script, nous ne
assetsMetadata
objets
assetsMetadata
un par un sous la forme d'un fichier de liste. Au lieu de cela, nous effectuons une fusion profonde des objets - nous les combinons et
assetsMetadata
un seul objet
assetsMetadata
.
En général, ce n'est rien d'autre qu'une fusion «logique» de fichiers Sketch et de leurs ressources en un seul fichier. Cependant, la logique n'est pas aussi simple qu'il y paraît. Voici un diagramme que nous avons créé pour tenter de comprendre ce qui se passe lorsque des icônes portant le même nom (et éventuellement soumises à des tests A / B) dans différents fichiers sont associées à la même marque:

Création de fichiers prêts à l'emploi dans différents formats pour différentes plateformes
La dernière étape de notre processus consiste à créer directement des fichiers d'icônes dans différents formats pour différentes plates-formes (PDF pour iOS, SVG / JSX pour Web et VectorDrawable pour Android).
Comme vous pouvez le voir d'après le nombre de paramètres transmis aux fonctions
generateAssets[format][platform]
, cette partie du pipeline est la plus complexe. C'est là que le processus commence à se décomposer et à changer en fonction de la plateforme. Ci-dessous, vous verrez le déroulement logique du script dans son ensemble et comment la partie liée à la génération de ressources est divisée en trois processus similaires mais différents:

Pour créer des ressources prêtes à l'emploi avec les couleurs correctes correspondant à la marque en cours de traitement, nous devrons effectuer quelques manipulations supplémentaires avec les fichiers JSON. Nous parcourons toutes les couches auxquelles le style général est appliqué et remplaçons les valeurs de couleur par les couleurs du jeton de conception de la marque.
Pour générer des fichiers pour Android, vous devez effectuer une action supplémentaire (à ce sujet un peu plus tard): nous changeons la propriété de
fill-rule
de chaque couche de
even-odd
Ă
non-zero
(ceci est contrôlé par la propriété
windingRule
de l'objet JSON, dans laquelle 1 signifie "impair / pair" , et 0 est "différent de zéro").
Après avoir effectué ces manipulations, nous replaçons les fichiers JSON dans un fichier Sketch standard pour traiter et exporter des ressources avec des propriétés mises à jour (les fichiers clonés et mis à jour sont des fichiers Sketch ordinaires, ils peuvent être ouverts, affichés, modifiés, enregistrés, etc. )
Après cela, nous utilisons SketchTool (enveloppé
sous Node ) pour exporter automatiquement toutes les ressources dans des formats adaptés aux plates-formes. Pour chacun des fichiers associés à la marque (ou plutôt, leurs versions clonées et mises à jour), nous exécutons la commande suivante:
sketchtool.run(`export slices ${cloneSketchFile} --formats=svg --scales=1 --output=${destinationFolder} --overwriting`);
Comme vous pouvez le deviner, cette commande exporte les ressources vers le dossier de destination dans un format spécifique, en utilisant éventuellement la mise à l'échelle (nous conservons l'échelle d'origine pour l'instant). La clé ici est l'option
-overwriting
: tout comme nous faisons une fusion profonde des objets
assetsMetadata
(correspondant aux fichiers Sketch «logiques»), lors de l'exportation, nous fusionnons de nombreux fichiers dans un répertoire (lié à la marque / plateforme). Cela signifie que si la ressource - identifiée par le nom de la couche - existait déjà dans le fichier Sketch précédent, elle sera remplacée lors de la prochaine exportation. Encore une fois, ce n'est rien de plus qu'une opération de fusion normale.
Cependant, dans cet exemple, certaines ressources peuvent se révéler être des «fantômes». Cela se produit lorsque l'icône du fichier est soumise à un test A / B, mais est remplacée dans le fichier suivant. Ensuite, les fichiers de variantes sont exportés vers le dossier de destination, ont un lien correspondant à la ressource dans l'objet
assetsMetadata
(avec leur clé et leurs propriétés), mais ne sont associés à aucune ressource de base (en raison de la fusion en profondeur des objets
assetsMetadata
). Ces fichiers seront supprimés ultérieurement, avant de terminer le processus.
Comme déjà mentionné, différentes plates-formes nécessitent différents formats de sortie. Les fichiers iOS s'adaptent aux PDF et nous pouvons les exporter directement à l'aide de la commande SketchTool. Les fichiers JSX sont requis pour Mobile Web et VectorDrawable pour Android. Pour cette raison, nous exportons des ressources au format SVG vers un dossier temporaire et après cela nous les traitons.
PDF pour iOS
Curieusement, PDF est le seul (?) Format pris en charge par Xcode et OS / iOS pour l'importation et le rendu des ressources vectorielles (
voici une brève explication du choix
d' Apple).
Comme nous pouvons exporter directement au format PDF via SketchTool, aucune étape supplémentaire n'est requise: il suffit d'enregistrer les fichiers directement dans le dossier de destination, et c'est tout.
Fichiers Web React / JSX
Dans le cas du Web, nous utilisons la bibliothèque SVGR Node, qui vous permet de convertir SVG en composants React. Cependant, nous voulons faire quelque chose de brusquement: «coloriser dynamiquement» l'icône lors de l'exécution (les couleurs sont tirées des jetons). Pour ce faire, avant la conversion, nous modifions les valeurs de
fill
des vecteurs auxquels le style général a été précédemment appliqué aux valeurs des jetons correspondant à ce style.
Donc, si le fichier
badge-feature-like.svg exporté depuis Sketch ressemble à ceci:
<?xml version="1.0" encoding="UTF-8"?> <svg width="128px" height="128px" viewBox="0 0 128 128" version="1.1" xmlns="<a href="http://www.w3.org/2000/svg">http://www.w3.org/2000/svg</a>" xmlns:xlink="<a href="http://www.w3.org/1999/xlink">http://www.w3.org/1999/xlink</a>"> <!-- Generator: sketchtool 52.2 (67145) -<a href="http://www.bohemiancoding.com/sketch"> http://www.bohemiancoding.com/sketch</a> --> <title>badge-feature-like</title> <desc>Created with sketchtool.</desc> <g id="Icons" fill="none" fill-rule="evenodd"> <g id="badge-feature-like"> <circle id="circle" fill="#E71032" cx="64" cy="64" r="64"> <path id="Shape" fill="#FFFFFF" d="M80.4061668,..."></path> </g> </g> </svg>
alors l'
icĂ´ne finale de ressource /
badge-fonction-like.js ressemblera Ă ceci:
/* This file is generated automatically - DO NOT EDIT */ /* eslint-disable max-lines,max-len,camelcase */ const React = require('react'); module.exports = function badge_feature_like({ tokens }) { return ( <svg data-origin="pipeline" viewBox="0 0 128 128"> <g fill="none" fillRule="evenodd"> <circle fill={tokens.TOKEN_COLOR_FEATURE_LIKED_YOU} cx={64} cy={64} r={64} /> <path fill="#FFF" d="M80.4061668,..." /> </g> </svg> ); };
Comme vous pouvez le voir, nous avons remplacé la couleur de
fill
statique par une couleur dynamique qui prend des valeurs des jetons (elles peuvent ĂŞtre mises Ă disposition pour le composant React
<Icon/>
via l'API Context, mais c'est une autre histoire).
Ce remplacement est possible grâce aux métadonnées Sketch pour les actifs de l'objet
assetsMetadata
: en parcourant récursivement les couches, vous pouvez créer un sélecteur DOM (pour l'exemple ci-dessus,
#Icons
#badge-feature-like #circle
) et l'utiliser pour rechercher un nœud dans l'arborescence SVG et remplacer sa valeur attribut
fill
(pour cela, nous avons besoin de la bibliothèque
cheerio ).
Fichiers vectoriels pour Android
Android prend en charge les graphiques vectoriels en utilisant le format vectoriel personnalisé
VectorDrawable . Habituellement, la conversion de SVG en VectorDrawable se fait
directement dans Android Studio . Cependant, nous voulions automatiser entièrement le processus, donc nous cherchions un moyen de convertir en utilisant du code.
Après avoir étudié divers outils et bibliothèques, nous avons
opté pour
svg2vectordrawable . Il est non seulement activement pris en charge (en tout cas, plus actif que tout le monde), mais aussi plus fonctionnel que les autres.
Les réalités sont que VectorDrawable et SVG ne sont pas les mêmes dans leurs fonctionnalités: certaines fonctions SVG (par exemple, les dégradés radiaux et la mise en évidence complexe) ne sont pas prises en charge par VectorDrawable, tandis que d'autres ont commencé à être prises en charge assez récemment (à partir d'Android API 24). L'un des problèmes qui en résulte est que les anciennes versions (jusqu'à 24)
ne prennent pas en charge la valeur paire-impaire de l'attribut fill-rule . Cependant, chez Badoo, nous avons besoin du support pour Android 5 et supérieur. C'est pourquoi, à l'une des étapes précédentes, nous avons amené le
fill
chaque vecteur des fichiers Sketch Ă une valeur
non-zero
.
En principe, les concepteurs peuvent effectuer cette action manuellement:

Mais c'est facile à oublier et à commettre une erreur. Par conséquent, nous avons décidé d'ajouter une étape supplémentaire au processus pour Android, au cours de laquelle tous les vecteurs dans JSON sont automatiquement convertis en
non-zero
. Cela est fait de sorte que lors de l'exportation d'icônes vers SVG, elles soient déjà au format requis, et chaque objet VectorDrawable créé est pris en charge par les appareils sur Android 5.
Le fichier
badge-feature-like.xml terminé ressemble à ceci:
<!-- This file is generated automatically - DO NOT EDIT --> <vector xmlns:android="<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>" android:width="128dp" android:height="128dp" android:viewportWidth="128" android:viewportHeight="128"> <path android:fillColor="?color_feature_liked_you" android:pathData="M64 1a63 63 0 1 0 0 126A63 63 0 1 0 64 1z" /> <path android:fillColor="#FFFFFF" android:pathData="M80.406 ..." /> </vector>
Dans les fichiers VectorDrawable, nous insérons des noms de variables pour les couleurs de
fill
, qui sont associées aux jetons de conception via des styles courants dans les applications Android.

Il est Ă noter qu'Android Studio a des exigences strictes pour l'organisation des ressources: pas de sous-dossiers et de majuscules dans les noms! Nous avons donc dĂ» trouver un nouveau format pour les noms d'icĂ´nes: dans le cas des ressources Ă tester, ils ressemblent Ă ceci:
ic_icon-name__experiment-name__variant-name
.
Dictionnaire JSON en tant que bibliothèque de ressources
Une fois les fichiers de ressources enregistrés au format final, il ne reste plus qu'à collecter toutes les méta-informations obtenues lors de l'assemblage et à les enregistrer dans un «dictionnaire» à utiliser lorsque les ressources sont importées et utilisées par la base de code de différentes plateformes.
Après avoir extrait une liste plate d'icônes de l'objet
assetsMetadata
nous le
assetsMetadata
vérifiant chacune d'elles:
- S'agit-il d'une ressource régulière (par exemple,
tabbar-livestream
); si oui, alors laissez-le;
- s'il s'agit d'une option pour un test A / B (par exemple, experiment / tabbar-livestream [variant] ), nous associons son nom, son chemin, les noms du test A / B et sa variante à la propriété
abtests
la ressource de base (dans notre cas, il s'agit de tabbar-livestream ), après quoi nous supprimons l'enregistrement de la variante de la liste / objet (seul l'élément «base» compte);
- s'il s'agit d'un «fantôme», supprimez le fichier et supprimez l'entrée de la liste / objet.
Après avoir terminé ce processus, le dictionnaire contiendra une liste de toutes les icônes de base (et leurs tests A / B, le cas échéant), et seulement eux. Les informations sur chacun d'eux incluent le nom, la taille, le chemin d'accès et, si l'icône est soumise à des tests A / B, des informations sur ses différentes options.
Le dictionnaire est enregistré au format JSON dans le dossier de destination de la
marque et de la
plateforme . Voici, par exemple, le fichier
assets.json généré pour l'application Blendr pour Mobile Web:
{ "platform": "mw", "brand": "blendr", "assets": { "badge-feature-like": { "assetname": "badge-feature-like", "path": "assets/badge-feature-like.jsx", "width": 64, "height": 64, "source": "icons_common" }, "navigation-bar-edit": { "assetname": "navigation-bar-edit", "path": "assets/navigation-bar-edit.jsx", "width": 48, "height": 48, "source": "icons_common" }, "tabbar-livestream": { "assetname": "tabbar-livestream", "path": "assets/tabbar-livestream.jsx", "width": 128, "height": 128, "source": "icons_blendr", "abtest": { "this__is_an_experiment": { "control": "assets/this__is_an_experiment/tabbar-livestream__control.jsx", "variant1": "assets/this__is_an_experiment/tabbar-livestream__variant1.jsx", "variant2": "assets/this__is_an_experiment/tabbar-livestream__variant2.jsx" }, "a_second-experiment": { "control": "assets/a_second-experiment/tabbar-livestream__control.jsx", "variantA": "assets/a_second-experiment/tabbar-livestream__variantA.jsx" } } }, ... } }
Il ne reste plus qu'Ă emballer tous les dossiers de
ressources dans des archives ZIP pour un téléchargement plus facile.
Résumé
Le processus décrit dans l'article, du clonage et de la manipulation des fichiers Sketch à l'exportation et à la conversion des ressources dans des formats pris en charge par les plateformes et à l'enregistrement des méta-informations collectées dans la bibliothèque de ressources, est répété avec chaque marque annoncée dans le script de construction.
Voici une capture d'écran montrant l'apparence des dossiers
src et
dist une fois le processus terminé:

À ce stade, à l'aide d'une commande simple, vous pouvez télécharger toutes les ressources (JSON, ZIP et fichiers de ressources) vers le stockage distant et les rendre disponibles pour toutes les plates-formes pour le téléchargement et l'utilisation dans la base de code.
La manière exacte dont les plateformes reçoivent et traitent les ressources (à l'aide de scripts personnalisés créés spécifiquement à cet effet) ne dépasse pas le cadre de cet article. Et cette question sera probablement traitée dans l'un des articles suivants par un de mes collègues.
Conclusion (et leçons apprises)
J'ai toujours aimé Sketch. Pendant de nombreuses années, le programme a été l'outil par défaut pour les développeurs et les concepteurs. Par conséquent, j'étais très curieux d'apprendre des outils d'intégration comme
html-sketchapp et d'autres outils similaires que nous pourrions utiliser dans le flux de travail et nos pipelines.
Comme beaucoup d'autres ,
j'ai toujours œuvré pour un tel processus (idéal):

Cependant, je dois admettre que j'ai commencé à douter que Sketch soit un outil approprié, surtout compte tenu du système de conception. Par conséquent, j'ai commencé à regarder d'autres services, tels que Figma avec ses API ouvertes et Framer X avec une intégration pratique avec React, parce que je ne ressentais pas le mouvement de Sketch vers l'intégration avec le code (quel qu'il soit).
Donc, ce projet m'a convaincu. Pas complètement, mais à bien des égards.
Bien que Sketch n'ouvre pas ses API, le dispositif même de la structure interne de ses fichiers sert comme une sorte d'API «non officielle». Les créateurs peuvent utiliser des noms chiffrés ou masquer des clés dans les objets JSON, mais à la place, ils adhèrent à une convention de dénomination claire, lisible et conceptuelle. Je ne pense pas que ce soit un accident.
Le fait que les fichiers Sketch puissent être gérés de cette manière m'a ouvert la voie à de nombreux développements et améliorations futurs: des plugins pour vérifier le nom, la stylisation et la structure des couches pour les icônes à l'intégration avec notre Wiki et la documentation de notre système de conception (mutuelle). En créant des applications Node sur
Electron ou
Carlo , nous pouvons faciliter la tâche des concepteurs pour effectuer de nombreuses tâches de routine.
( , ) , Sketch- Cosmos « » — - Cosmos. , ( ; , — ). , — , , .
, Sketch- , , MVP-, . , , . , , -, — , . , .
:
,
. ,
.
, , — . , , , (, A/B-), Node.js Sketch.
! .
Remerciements
(Mobile Web), ,
(Android)
(iOS), .
, ! .