Skip to content
Read/write/manipulate Sketch files in Node without Sketch plugins!
JavaScript HTML
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github Creating initial file from template Jan 8, 2019
__examples__ fix(symbols): adding symbol functionality (#31) Jul 8, 2019
__tests__ fix: use getters for Models (#52) Sep 5, 2019
docs docs(tracking): updating tracking pixel Feb 9, 2019
models feat: use const enum to define relationships between getter and model ( Sep 16, 2019
scripts docs: adding docsify and jsdoc-to-markdown for docs site (#2) Jan 26, 2019
utils feat: add bitmap model (#48) Sep 10, 2019
.commitlintrc.json chore(commitlint): fixing commitlint settings Jan 29, 2019
.eslintrc.json docs: adding docsify and jsdoc-to-markdown for docs site (#2) Jan 26, 2019
.gitignore Initial commit Jan 9, 2019
.prettierrc.js Adding prettier, eslint, etc Jan 25, 2019
.travis.yml ci(travis): getting it to deploy on master commits (#20) May 16, 2019
CODE_OF_CONDUCT.md Creating initial file from template Jan 8, 2019
CONTRIBUTING.md Creating initial file from template Jan 8, 2019
LICENSE Creating initial file from template Jan 8, 2019
NOTICE Creating initial file from template Jan 8, 2019
README.md docs: adding docsify and jsdoc-to-markdown for docs site (#2) Jan 26, 2019
index.d.ts feat: TypeScript type definition (#23) Jun 11, 2019
index.js Fixing prettier and lint things Jan 25, 2019
jsdoc.json Cleaning up code structure, adding jsdoc Jan 25, 2019
package-lock.json feat: add bitmap model (#48) Sep 10, 2019
package.json feat: add bitmap model (#48) Sep 10, 2019
tsconfig.json feat: TypeScript type definition (#23) Jun 11, 2019

README.md

Sketch Constructor

This library provides helpers and classes that make it easy to read/write/manipulate Sketch files in Javascript, without Sketch installed!

⚠️ Warning ⚠️

This library is a work in progress, use at your own risk. But feel free to help out where you see bugs or incomplete things! Also, because this library is not using any Sketch APIs/libraries and manipulating the underlying sketch files, the internal file API might change in the future. We will do our best to keep up with any Sketch changes and communicate any breaking API changes.

Why?

If you want to produce Sketch assets for your design team that are generated from your production codebase in a reliable and consistent way, like part of a build process or CI/CD pipeline. Or maybe you want to have your source of truth for your design tokens or components in Sketch, you can use this to extract that data out into your codebase.

What can you do with this?

  • Generate Sketch files programmatically without actually running Sketch (no plugins!)
  • Use Sketch as input to create resources/documentation for a design system
  • Build Sketch files in a CI/CD pipeline
  • Read a Sketch file as a template, hydrate it with data, output a new Sketch file

How is this different from html-sketchapp or react-sketchapp?

Those tools are great and very powerful, but rely on creating sketch plugins on the fly and manipulating a Sketch document that is open on your computer. They are also focused on rendering sketch files and not using a Sketch file as input or data. This tool however helps you directly manipulate and generate Sketch files without a sketch plugin or even having Sketch open or installed.

Installation

This library is published as an npm module, you can install it via npm or yarn:

npm install --save-dev sketch-constructor
yarn add sketch-constructor

Usage

Creating a Sketch file

Creating a completely new Sketch file from scratch, programmatically in node.

const {Sketch, Page, Artboard} = require('sketch-constructor');

// Without a path it creates an empty sketch class to work with
const newSketch = new Sketch();

// Create a new Page instance
const page = new Page({ });

// Add an artboard to the page
const artboard = new Artboard({});
page.addArtboard(artboard);

// Add the page to the Sketch instance
newSketch.addPage( page );

// You can also add a page by giving it an object, the arguments
// are the same as that of the Page constructor
newSketch.addPage({
  name: 'My Page'
});

// Creates the sketch file
newSketch.build('newSketch.sketch');

Read/manipulate an existing Sketch file

Getting data from or manipulating an existing Sketch file.

const {Sketch, Page} = require('sketch-constructor');

// static method fromFile returns a promise
Sketch.fromFile(`${process.cwd()}/__tests__/__sketch-files/test.sketch`)
  .then((sketch) => {
    // You can now get data from the sketch instance
    // For example, get all the Groups in a particular artboard
    // and page that has a name that includes 'test'
    sketch.getPage('Page 1')
      .getArtboard('Artboard 1')
      .getGroups((group) => group.name.includes('test'));

    // Or manipulate the sketch file the same way you would
    // with a new sketch instance
    var page = new Page({});
    sketch.addPage( page );
  });

Models

These are all the classes Sketch uses in it's JSON schema. They should all map 1:1 with any object in the JSON that has _class attribute. All the models are ES6 classes which have instance properties that map 1:1 with the attributes of JSON schema of that class. This makes it easy automatically create class instances from a sketch document as well as write the JSON of a sketch document because calling JSON.stringify() on a class will only output instance properties.

All classes have the same constructor method signature:

class Layer {
  constructor(args = {}, json) {}
}

If you are creating new classes from scratch, you will supply the constructor with a single object like this:

let text = new Text({
  // options
});

This options object does NOT map 1:1 with the underlying JSON schema of the class. It simplifies the API so that you don't have to understand the underlying structure and to hopefully future-proof the classes. A simple example is the Color class:

let color = new Color("#fff")
console.log(JSON.stringify(color, null, 2));
/*
{
  "_class": "color",
  "alpha": 1,
  "blue": 1,
  "green": 1,
  "red": 1
}
*/

Rather than having to pass in the rgba channels (out of 1 not 255 like CSS), you can pass in anything that Tiny Color can understand.

For most classes there are helper methods to make interacting with them easier. For example, the Color class has all of the Tiny Color methods so you can modify the color or get different representations of it.

If you start with an existing Sketch file by using Sketch.fromFile(filePath), the library will recursively create all the underlying classes so you don't have to worry about manually instantiating the classes. For example:

const { Sketch, Page, Artboard } = require('sketch-constructor');

Sketch.fromFile('myFile.sketch')
  .then((sketch) => {
    // create an array of Group instances
    const groups = sketch.getPage('Page 1')
      .getArtboard('Artboard 1')
      .getGroups((group) => group.name.includes('test'));

    // Now you can use any Group instance methods like adding layers
    groups.forEach((group) => {
      group.addLayer(
      new Text({
        string: "Hello",
        name: "Hello",
        fontSize: 24,
        color: "#ccc",
        frame: {
          width: 200,
          height: 50,
          x: 0,
          y: 120,
        }
      })
      )
    })
  })

Contributing

We love contributors! This project is still WIP so any help would be amazing. Please take a look at our contributing docs

License

This library is licensed under the Apache 2.0 License.

You can’t perform that action at this time.