Sketch + Node.js: genera iconos para muchas plataformas y marcas. Parte 2



Esta es la segunda parte del artículo sobre la creación de una herramienta que puede exportar todos los íconos ubicados en un archivo de Sketch: en diferentes formatos, para diferentes plataformas, con la posibilidad de probar A / B de cada ícono.

Puedes leer la primera parte desde el enlace .



La última vez, preparamos archivos de croquis que contienen todos los iconos en los estilos correctos y con los nombres correctos. Es el turno de escribir código.

Baste decir que pasamos por prueba y error. Después de que el líder de nuestro equipo, Nihil Verma , quien sentó las bases del guión, desarrolló el código fuente clave, comencé un proceso que requería al menos tres fases de refactorización y muchas modificaciones. Por esta razón, no entraré en los detalles de la creación del guión y me centraré en cómo funciona hoy, en su forma final.

Construir script


El script de compilación escrito en Node.js es bastante sencillo en su trabajo: al importar las dependencias, declarar una lista de archivos de Sketch para procesar (es una lista de marcas, cada una de las cuales tiene una lista de archivos relacionados) y asegurarse de que Sketch esté instalado en el cliente , el script procesa las marcas a su vez, realizando una serie de acciones con cada una de ellas.

  1. Toma tokens de diseño apropiados para las marcas (necesitamos valores de color).
  2. Clona archivos de bocetos asociados con la marca, los descomprime para extraer archivos JSON internos y procesa algunos de sus valores internos (más sobre eso más adelante).
  3. Lee los metadatos necesarios de estos archivos JSON ( document.json , meta.json y pages / pageUniqueID.json ). Estamos interesados ​​en listas de estilos comunes y recursos / íconos contenidos en archivos.
  4. Después de algunas manipulaciones más con archivos JSON, recrea el archivo y, utilizando archivos Sketch (clonados y actualizados), exporta y crea los archivos de salida finales para tres plataformas (iOS, Android, Web móvil).

Las partes relevantes del script de compilación se pueden encontrar aquí:

// ... 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   }); }); } 

De hecho, el código de la tubería es mucho más complicado. La razón de esta complejidad radica en las prepareSketchFiles , getSketchMetadata y generateAssets[format][platform] . A continuación intentaré describirlos con más detalle.

Preparar archivos de croquis


El primer paso en el proceso de ensamblaje es la preparación de archivos de Sketch, que luego se utilizarán para exportar recursos para varias plataformas.

Los archivos asociados con una marca en particular (por ejemplo, en el caso de Blendr, estos son los archivos icons_common.sketch y icons_blendr.sketch ) se clonan en una carpeta temporal (más precisamente, en una subcarpeta con el nombre de la marca que se procesa) y se descomprimen.

Luego se procesan los archivos JSON. Se agrega un prefijo al nombre de los recursos sujetos a las pruebas A / B; por lo tanto, durante la exportación, se guardarán en una subcarpeta con un nombre predefinido (correspondiente al nombre único del experimento). Puede entender si un recurso está sujeto a pruebas A / B por el nombre de la página en la que está almacenado: si es así, el nombre contendrá el prefijo " XP_ ".



En el ejemplo anterior, los recursos exportados se almacenarán en una subcarpeta de " this__is_an_experiment " con un nombre de archivo de la forma " icon-name [variant-name] .ext ".

Lectura de metadatos de croquis


El segundo paso importante es extraer todos los metadatos necesarios de los archivos de Sketch, o más bien, de los archivos JSON internos. Como vimos anteriormente, estos son dos archivos principales ( document.json y meta.json ) y archivos de página ( pages / pageUniqueId.json ).

El archivo document.json se usa para obtener la lista de estilos comunes que aparece bajo la propiedad del objeto 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      }    },    ... 

Almacenamos información básica sobre cada estilo en un objeto de formato clave-valor. Se usará más adelante cuando necesitemos extraer el nombre del estilo basado en una ID única (propiedad do_objectID en 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, }; }); 

Ahora vamos al archivo meta.json y obtenemos una lista de páginas. Estamos interesados ​​en su unique-id y name unique-id :

 { "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]"      }    }  }, 

Luego leemos los archivos JSON correspondientes a cada página en la carpeta de páginas (repito que los nombres de los archivos tienen la forma [pageUniqueId] .json ) y estudiamos los recursos almacenados en esta página (se ven como capas). Por lo tanto, obtenemos el nombre , el ancho / alto de cada ícono, los metadatos del boceto para el ícono de esta capa, y si estamos tratando con una página de experimento , entonces el nombre de la prueba A / B y una variante de este ícono.

Nota : el objeto page.json tiene un dispositivo muy complejo, por lo que no me detendré en él. Si está interesado en lo que hay dentro, le aconsejo que cree un nuevo archivo de Sketch vacío, que agregue algún contenido y lo guarde; luego cambie el nombre de su extensión a ZIP, descomprímalo y examine uno de los archivos en la carpeta de páginas.

En el proceso de procesamiento de mesas de trabajo, también crearemos una lista de experimentos (y recursos relacionados). Lo necesitaremos para determinar qué variaciones del ícono se utilizan en cada experimento: los nombres de las variaciones del ícono se adjuntan al objeto "base".

Para cada archivo de Sketch assetsMetadata que se procesa, creamos un objeto de assetsMetadata que se ve así:

 { "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  ... 

Como puede ver, en el experimento, un solo icono (en este caso, barra de navegación-editar ) puede corresponder a muchos recursos. Al mismo tiempo, el mismo icono puede aparecer bajo el mismo nombre en otro archivo de boceto asociado con la marca. Esto es muy útil : utilizamos este truco para compilar un conjunto común de iconos y luego identificamos opciones específicas según la marca. Es por eso que declaramos los archivos de Sketch asociados con una marca en particular como una matriz:

 const SKETCH_FILES = { badoo: ['icons_common'], blendr: ['icons_common', 'icons_blendr'], fiesta: ['icons_common', 'icons_fiesta'], hotornot: ['icons_common', 'icons_hotornot'], }; 

En este caso, el orden es de fundamental importancia. De hecho, en la función getSketchMetadata llamada por el script, no assetsMetadata objetos assetsMetadata uno a la vez como un archivo de lista. En su lugar, realizamos una fusión profunda de objetos: los combinamos y devolvemos un único objeto assetsMetadata .

En general, esto no es más que una fusión "lógica" de archivos Sketch y sus recursos en un solo archivo. Sin embargo, la lógica no es tan simple como parece. Aquí está el diagrama que creamos en un intento de descubrir qué sucede cuando los iconos con el mismo nombre (y posiblemente sujetos a pruebas A / B) en diferentes archivos están asociados con la misma marca:



Creación de archivos listos para usar en diferentes formatos para diferentes plataformas.


La etapa final de nuestro proceso es crear directamente archivos de iconos en diferentes formatos para diferentes plataformas (PDF para iOS, SVG / JSX para Web y VectorDrawable para Android).

Como puede ver en la cantidad de parámetros pasados ​​a las funciones generateAssets[format][platform] , esta parte de la tubería es la más compleja. Aquí es donde el proceso comienza a romperse y cambiar según la plataforma. A continuación, verá el curso lógico del script en su conjunto y cómo la parte relacionada con la generación de recursos se divide en tres procesos similares pero diferentes:



Para crear recursos listos para usar con los colores correctos correspondientes a la marca que se procesa, necesitaremos realizar algunas manipulaciones más con los archivos JSON. Revisamos todas las capas a las que se aplica el estilo general y reemplazamos los valores de color con los colores del token de diseño de la marca.

Para generar archivos para Android, debe realizar una acción adicional (al respecto un poco más adelante): cambiamos la propiedad de la fill-rule de cada capa de even-odd a even-odd a non-zero (esto está controlado por la propiedad windingRule del objeto JSON, en el que 1 significa "impar / par" , y 0 es "no es igual a cero").

Una vez realizadas estas manipulaciones, empaquetamos los archivos JSON en un archivo Sketch estándar para procesar y exportar recursos con propiedades actualizadas (los archivos clonados y actualizados son archivos Sketch normales, se pueden abrir, ver, editar, guardar, etc. )

Después de eso, usamos SketchTool (envuelto bajo Node ) para exportar automáticamente todos los recursos en formatos adecuados para plataformas. Para cada uno de los archivos asociados con la marca (o más bien, sus versiones clonadas y actualizadas), ejecutamos el siguiente comando:

 sketchtool.run(`export slices ${cloneSketchFile} --formats=svg --scales=1 --output=${destinationFolder} --overwriting`); 

Como puede suponer, este comando exporta recursos a la carpeta de destino en un formato específico, opcionalmente usando escala (mantenemos la escala original por ahora). La clave aquí es la opción de -overwriting : al igual que hacemos una fusión profunda de los objetos de objetos de assetsMetadata (correspondientes a los archivos de boceto "lógicos"), al exportar fusionamos muchos archivos en un directorio (relacionado con la marca / plataforma). Esto significa que si el recurso, identificado por el nombre de la capa, ya existía en el archivo Sketch anterior, se sobrescribirá durante la próxima exportación. De nuevo, esto no es más que una operación de fusión normal.

Sin embargo, en este ejemplo, algunos recursos pueden resultar ser "fantasmas". Esto sucede cuando el icono en el archivo está sujeto a pruebas A / B, pero se sobrescribe en el archivo posterior. Luego, los archivos variantes se exportan a la carpeta de destino, tienen un enlace correspondiente al recurso en el objeto assetsMetadata (con su clave y propiedades), pero no se asocian con ningún recurso base (debido a la fusión profunda de los objetos assetsMetadata ). Dichos archivos se eliminarán más tarde, antes de completar el proceso.



Como ya se mencionó, diferentes plataformas requieren diferentes formatos de salida. Los archivos de iOS se ajustan a los PDF y podemos exportarlos directamente con el comando SketchTool. Los archivos JSX son necesarios para Mobile Web y VectorDrawable para Android. Por esta razón, exportamos recursos en formato SVG a una carpeta temporal y luego los procesamos.

PDF para iOS


Curiosamente, PDF es el único formato (?) Que admite Xcode y OS / iOS para importar y representar recursos vectoriales ( aquí hay una breve explicación de la elección de Apple).

Como podemos exportar directamente a PDF a través de SketchTool, no se requieren pasos adicionales: simplemente guarde los archivos directamente en la carpeta de destino, y eso es todo.

Reaccionar / archivos web JSX


En el caso de la Web, utilizamos el nodo de biblioteca SVGR, que le permite convertir SVG a componentes React. Sin embargo, queremos hacer algo abruptamente: "colorear dinámicamente" el ícono en tiempo de ejecución (los colores se toman de los tokens). Para hacer esto, antes de convertir, cambiamos los valores de fill de los vectores a los que se aplicó previamente el estilo general a los valores de los tokens correspondientes a este estilo.

Entonces, si el archivo badge-feature-like.svg exportado desde Sketch se ve así:

 <?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> 

entonces el icono final resource / badge-feature-like.js se verá así:

 /* 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> ); }; 

Como puede ver, reemplazamos el color de fill estático por uno dinámico que toma valores de tokens (pueden estar disponibles para el componente Reaccionar <Icon/> través de la API de contexto, pero esta es una historia diferente).

Este reemplazo es posible gracias a los metadatos de Sketch para los activos del objeto assetsMetadata : yendo recursivamente a través de las capas, puede crear un selector DOM (para el ejemplo anterior, #Icons #badge-feature-like #circle ) y usarlo para buscar un nodo en el árbol SVG y reemplazar su valor atributo de fill (para esto necesitamos la biblioteca cheerio ).

VectorDrawable Files para Android


Android admite gráficos vectoriales utilizando el formato vectorial personalizado VectorDrawable . Por lo general, la conversión de SVG a VectorDrawable se realiza directamente en Android Studio . Sin embargo, queríamos automatizar completamente el proceso, por lo que estábamos buscando una forma de convertir usando código.

Después de estudiar varias herramientas y bibliotecas, nos decidimos por svg2vectordrawable . No solo es compatible activamente (en cualquier caso, más activo que todos los demás), sino también más funcional que el resto.

Las realidades son que VectorDrawable y SVG no son iguales en su funcionalidad: algunas funciones SVG (por ejemplo, gradientes radiales y resaltado complejo) no son compatibles con VectorDrawable, mientras que otras comenzaron a ser compatibles recientemente (comenzando con Android API 24). Uno de los problemas derivados de esto es que las versiones anteriores (hasta 24) no admiten el valor par-impar del atributo de regla de relleno . Sin embargo, en Badoo necesitamos soporte para Android 5 y superior. Es por eso que, en una de las etapas anteriores, llevamos el fill cada vector en los archivos de Sketch a un valor non-zero .

En principio, los diseñadores pueden realizar esta acción manualmente:



Pero esto es fácil de olvidar y cometer un error. Por lo tanto, decidimos agregar un paso adicional al proceso para Android, en el cual todos los vectores en JSON se convierten automáticamente a non-zero . Esto se hace para que al exportar iconos a SVG ya estén en el formato requerido, y cada objeto VectorDrawable creado sea compatible con dispositivos en Android 5.

El archivo badge-feature-like.xml terminado se ve así:

 <!-- 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> 

En los archivos de VectorDrawable, insertamos nombres de variables para colores de fill , que están asociados con tokens de diseño a través de estilos comunes en aplicaciones de Android.



Vale la pena señalar que Android Studio tiene requisitos estrictos para organizar los recursos: ¡no hay subcarpetas ni letras mayúsculas en los nombres! Así que tuvimos que crear un nuevo formato para los nombres de los íconos: en el caso de los recursos que se probarán, se verán así: ic_icon-name__experiment-name__variant-name .

Diccionario JSON como biblioteca de recursos


Una vez que los archivos de recursos se guardan en el formato final, solo queda recopilar toda la metainformación obtenida durante el ensamblaje y guardarla en un "diccionario" para usar cuando los recursos son importados y utilizados por la base de código de varias plataformas.

Después de extraer una lista plana de iconos del objeto assetsMetadata revisamos y verificamos cada uno de ellos:

  • ¿Es este un recurso regular (por ejemplo, tabbar-livestream ); si es así, simplemente déjalo;
  • Si esta es una opción para una prueba A / B (por ejemplo, experiment / tabbar-livestream [variante] ), asociamos su nombre, ruta, nombres de la prueba A / B y la variante con la propiedad abtests
    el recurso base (en nuestro caso es tabbar-livestream ), después de lo cual eliminamos el registro sobre la variante de la lista / objeto (solo importa el elemento "base");
  • si es un "fantasma", elimine el archivo y elimine la entrada de la lista / objeto.

Después de completar este proceso, el diccionario contendrá una lista de todos los íconos básicos (y sus pruebas A / B, si corresponde), y solo ellos. La información sobre cada uno de ellos incluye el nombre, el tamaño, la ruta y, si el icono está sujeto a pruebas A / B, información sobre sus diversas opciones.

El diccionario se guarda en formato JSON en la carpeta de destino para la marca y la plataforma . Aquí, por ejemplo, está el archivo assets.json generado para la aplicación Blendr para 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"      }    }  },  ... } } 

Ahora todo lo que queda es empacar todas las carpetas de activos en archivos ZIP para facilitar la descarga.

Resumen


El proceso descrito en el artículo, desde clonar y manipular archivos de boceto hasta exportar y convertir recursos a formatos compatibles con plataformas y guardar metainformación recopilada en la biblioteca de recursos, se repite con cada marca anunciada en el script de compilación.

Aquí hay una captura de pantalla que muestra la apariencia de las carpetas src y dist una vez que se completa el proceso:



En esta etapa, con un comando simple, puede cargar todos los recursos (JSON, ZIP y archivos de recursos) en el almacenamiento remoto y ponerlos a disposición de todas las plataformas para descargar y usar en la base de código.

La forma exacta en que las plataformas reciben y procesan los recursos (usando scripts personalizados creados específicamente para este propósito) no va más allá del alcance de este artículo. Y esta pregunta probablemente será cubierta en una de las siguientes publicaciones de uno de mis colegas.

Conclusión (y lecciones aprendidas)


Siempre me ha encantado Sketch. Durante muchos años, el programa ha sido la herramienta predeterminada para desarrolladores y diseñadores. Por lo tanto, tenía mucha curiosidad por aprender herramientas de integración como html-sketchapp y otras herramientas similares que podríamos usar en el flujo de trabajo y nuestras canalizaciones.

Yo, como muchos otros , siempre me he esforzado por tal proceso (ideal):



Sin embargo, debo admitir que comencé a dudar de que Sketch sea una herramienta adecuada, especialmente teniendo en cuenta el sistema de diseño. Por lo tanto, comencé a buscar otros servicios, como Figma con sus API abiertas y Framer X con una integración conveniente con React, porque no sentía el movimiento de Sketch hacia la integración con el código (lo que fuera).

Entonces, este proyecto me convenció. No completamente, pero de muchas maneras.

Aunque Sketch no abre sus API, el dispositivo mismo de la estructura interna de sus archivos sirve como una especie de API "no oficial". Los creadores podrían usar nombres cifrados u ocultar claves en objetos JSON, pero en su lugar se adhieren a una convención de nomenclatura clara, legible y conceptual. No creo que esto sea un accidente.

El hecho de que los archivos de boceto se puedan administrar de esta manera me ha abierto el camino a muchos desarrollos y mejoras futuros: desde complementos para verificar el nombre, estilización y estructura de capas para los iconos hasta la integración con nuestra Wiki y la documentación de nuestro sistema de diseño (mutuo). Al crear aplicaciones Node en Electron o Carlo , podemos facilitar que los diseñadores completen muchas tareas rutinarias.

( , ) , Sketch- Cosmos « » — - Cosmos. , ( ; , — ). , — , , .

, Sketch- , , MVP-, . , , . , , -, — , . , .

: , . , .

, , — . , , , (, A/B-), Node.js Sketch.

! .


(Mobile Web), , (Android) (iOS), .

, ! .

Source: https://habr.com/ru/post/442886/


All Articles