Sketch-Stickers icon indicating copy to clipboard operation
Sketch-Stickers copied to clipboard

Support auto-indexing libraries that don't have any metadata

Open romannurik opened this issue 7 years ago • 8 comments

  • Probably sort them at the bottom
  • Possibly make this opt-out using a setting

romannurik avatar May 16 '18 20:05 romannurik

I wrote a small script that for a given library imports all symbols to a document and creates the metadata for it. If needed I can share it with you in private?

tijmenvangurp avatar Feb 06 '19 17:02 tijmenvangurp

Oh that's wonderful! Any reason to keep it private? Would be a great public resource :)

romannurik avatar Feb 06 '19 17:02 romannurik

Haha. because I don't know if it is any good. And it is part of a plugin that I develop which I am not allowed to share. So some variables you would have to guess from where they are.

But here it is:

import { UI, sketchDoc, _, Text } from '../imports';
import { findPageOrCreatePage } from '../styles-overview/createStylesOverview';
import { metaData } from '../..';

export function generateStickersOverview() {
  let libraries = require('sketch/dom').getLibraries();

  const libraryName = metaData.libraryForStickers;

  const library = libraries.find(library => library.name === libraryName);
  if (!library) {
    UI.message(`⚠️ ${libraryName} not found. Are you sure it is added?`);
  }

  const symbolReferences = library.getImportableSymbolReferencesForDocument(sketchDoc);
  let stickersMetaData = [];
  let symbolInstances = [];
  let xIndex = 0;
  let yIndex = 0;

  symbolReferences.forEach((symbolReference, index) => {
    const symbolMaster = symbolReference.import();
    const instance = symbolMaster.createNewInstance();
    instance.frame.y = (index - yIndex) * 100;
    instance.frame.x = xIndex;
    symbolInstances.push(instance);
    const categoryName = getCategoryName(instance.name);
    instance.name = `${instance.name} ${categoryName}`;
    const componentName = categoryName.split('.')[0].replace(/-/g, '_');

    if (!stickersMetaData.find(instance => instance.name === componentName)) {
      let metadataObject = {};
      metadataObject.name = componentName;
      stickersMetaData.push(metadataObject);
    }
    const stickerNamePlusSubNAme = `${componentName}.${categoryName.split('.')[1]}`;
    if (!stickersMetaData.find(instance => instance.name === stickerNamePlusSubNAme)) {
      xIndex += 200;
      yIndex = index;
      instance.frame.y = (index - yIndex) * 100;
      instance.frame.x = xIndex;
      let metadataObject = {};
      metadataObject.name = stickerNamePlusSubNAme;
      stickersMetaData.push(metadataObject);
    }
  });

  stickersMetaData = _.orderBy(stickersMetaData, ['name'], ['asc']);
  let textLayer = textLayer = new Text({
    text: getStickersMetadata(stickersMetaData)
  });

  const stickersMetaDataPage = findPageOrCreatePage('stickers-metadata');
  stickersMetaDataPage.layers = [textLayer];
  const importedSymbolsPage = findPageOrCreatePage('imported-symbols');
  importedSymbolsPage.layers = symbolInstances;

}

function getStickersMetadata(stickersMetaData) {


  const sectionPrefix = '!StickerSection ';
  const title = 'title: ';
  const hideNames = 'hideNames: true';
  // const description = 'description: A description';
  let yamlStickersMetadata = '';
  stickersMetaData.forEach(stickerMetaData => {
    yamlStickersMetadata += `${sectionPrefix}${stickerMetaData.name}\n`;
    let sectionTitle = stickerMetaData.name.split('.')[1];
    if (sectionTitle) {
      sectionTitle = sectionTitle.replace('_', ' ');
    } else {
      sectionTitle = stickerMetaData.name.replace('@', '').replace('.', ' ').replace('_', ' ');
      sectionTitle = upperCasefirst(sectionTitle);
    }
    yamlStickersMetadata += `${title}${sectionTitle}\n`;
    yamlStickersMetadata += `${hideNames}\n`;
  });

  return yamlStickersMetadata;
}

function upperCasefirst(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}

function getCategoryName(name) {
  name = name.replace(/\d+\./g, '');
  name = name.replace(/\s/g, '');
  name = name.replace(/-/g, '_');
  name = name.split('/');
  //TODO: maybe these should be hardcoded somewhere else? Or User input?
  const listOfCategoryItems = ['small', 'medium', 'large'];
  let newName = '';
  name.forEach((namePart, index) => {
    if (index === 0) {
      newName = `@${name[0]}`;
    } else if (index === 1) {
      newName += `.${name[index]}`;
    } else if (listOfCategoryItems.includes(name[index])) {
      newName += `_${name[index]}`;
    }
  });
  return newName;
}

tijmenvangurp avatar Feb 06 '19 17:02 tijmenvangurp

You would probably need to make something like a picker from which a user can pick a library to generate the stickers file from. In my case, it is hardcoded and it is fine like that for me.

I used lodash to sort everything. Could probably be done better but gives a pretty neat result.

tijmenvangurp avatar Feb 06 '19 17:02 tijmenvangurp

I am still working on optimizing the script. How can I share something with you in private? I could probably strip out the sensitive info from the plugin and then share the plugin to you.

tijmenvangurp avatar Feb 25 '19 16:02 tijmenvangurp

Oh feel free to email me privately: roman at nurik dot net

romannurik avatar Feb 25 '19 16:02 romannurik

Would this request allow for layers/symbols to be used with Stickers without the need to tag them? If so, this would be amazing. A feature I would definitely use.

iamhenry avatar May 14 '19 18:05 iamhenry

Would be great to use it with any library without metadata as @iamhenry suggests.

ztotik avatar Jun 11 '19 10:06 ztotik