Coder Social home page Coder Social logo

penpot-export's Introduction

penpot-export

penpot-export is a tool designed to export your design tokens created in Penpot into ready-to-use code or parseable data files.

Currently, it is able to export page components as CSS and SCSS declarations, and typography and colors assets as CSS, SCSS or JSON (following the Second Editor' Draft of the W3C Design Tokens Community Group format spec).

📦 Packages

@penpot-export/cli (npm package) is a CLI tool to use penpot-export through the command line. It features a configuration file where you declare what will be exported, where in the file system and what format will use.

@penpot-export/core (npm package) contains the core functionality to retrieve the Penpot data, transform it and output it to the filesystem.

demos is a demostrative private package that contains some examples of how to use @penpot-export/cli.

🧑‍💻 Usage

⬇️ Installation

The recommended way to install the penpot-export CLI is as a development dependency on a project:

# npm
npm install @penpot-export/cli --save-dev

# yarn
yarn add @penpot-export/cli --dev

🔧 Configuration

penpot-export uses the Penpot public API of a Penpot instance of your choice. Before you can use penpot-export, you'll need a way to authenticate to that API. Generate an access token and save that value in a safe place.

You'll also need the file ID of an existing Penpot file in that Penpot instance. Open the Penpot file in your browser and copy the URL. Then run:

penpot-export inspect <YOUR FILE URL HERE>

It'll output something similar to this:

The following details are the result of inspecting the provided URL:
    Penpot instance: https://design.penpot.app/
    Workspace id: f542b13d-6fc1-8116-8002-fc0aaa3627ae
    File id: 52961d58-0a92-80c2-8003-2fc8ab8b34dd
    Page id: 38f1e350-296d-80f1-8002-fd390f93b03d

Grab the file ID and the Penpot instance.

With this, set up a penpot-export.config.js file at the root of your project declaring how your Penpot designs will be exported.

Example config file

penpot-export.config.js:

// @ts-check
require('dotenv').config()

if (typeof process.env.PENPOT_ACCESS_TOKEN !== 'string') {
  throw new Error('Missing PENPOT_ACCESS_TOKEN environment variable')
}

/**
 * @type {import('@penpot-export/core').UserConfig}
 */
const config = {
  instance: process.env.PENPOT_BASE_URL || undefined,
  accessToken: process.env.PENPOT_ACCESS_TOKEN,
  files: [
    {
      fileId: '4a499800-872e-80e1-8002-fc0b585dc061',
      colors: [
        {
          format: 'scss',
          output: 'src/styles/colors.css', // 👈 Path where your colors SCSS file should be generated.
        },
      ],
      typographies: [
        {
          format: 'json',
          output: 'src/styles/typographies.css', // 👈 Path where your typographies JSON file should be generated.
        },
      ],
    },
    {
      fileId: 'abea3ef6-4c19-808a-8003-01370d9cb586',
      pages: [
        {
          pageId: '71b1702b-2eb1-81d6-8002-f82a5f182088',
          format: 'css',
          output: 'src/styles/ui.css', // 👈 Path where your page components CSS file should be generated.
        },
      ],
    },
  ],
}

module.exports = config
Configuration schema

Config schema:

property type notes
instance (optional) string Defaults to https://design.penpot.app
accessToken string The access token used to authenticate to the instance above
files FileConfig object A list of files to export, each with its own configuration

FileConfig schema:

property type notes
fileId string The UUID of the file where assets will be exported
colors (optional) ColorsConfig A list of outputs for color assets
typographies (optional) TypographiesConfig A list of outputs for typography assets
pages (optional) PagesConfig A list of outputs for page components

AssetConfig (ColorsConfig, TypographiesConfig, PagesConfig) schema:

property type notes
output string Relative route where your file should be generated
format css scss
fileId string (only for PagesConfig) The UUID of the page from where components will be exported

▶️ Usage

Once you've set up the penpot-export.config.js file, simply run the following command to generate your CSS files:

penpot-export

This will read your Penpot design file and generate the declared files.

⌨️ Development

Using Yarn Workspaces

This project is written in TypeScript and utilizes Yarn Workspaces to manage multiple packages within a single repository. This allows us to house the source code of the penpot-export modules and demos in separate packages, streamlining development and testing.

Why Yarn Workspaces?

Your dependencies can be linked together, which means that your workspaces can depend on one another while always using the most up-to-date code available. - Reference

Local Development

For the "demos" package to utilize the local version of the penpot-export command you're developing, it's essential first to compile the TypeScript code from the penpot-export package.

Handy Commands

To facilitate the development process, we've set up the following commands that can be run at the repository's root:

  • yarn dev: Runs the CLI tool in development mode. Ideal for making changes and seeing real-time results.
  • yarn build: Compiles the TypeScript code in production mode. Ensure you run this command before testing the tool in the demos package.
  • yarn demo: Runs the penpot-export command within the demos package per demo. It's handy for quickly testing implementations after making changes to the source code.

We recommend following this workflow: make changes to the code, run yarn build, and then yarn demo to test your changes.

penpot-export's People

Contributors

enriquebv avatar roberto-red avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

penpot-export's Issues

Decouple core from side-effects

Description

@penpot-export/core currently logs to the console and write files, without any way to control that behaviour for the consumer.

This may be undesired for some use-cases. E.g. someone that wants to hook into the file before it's written to use PostCSS or CSSTree or apply any transformation.

Expected output

Move logging to the CLI. This could be made injecting a logger function. But I'll just prefer to use a generator function in core and use message passing with the CLI, then let the CLI log the way it wants.

Return file contents instead of writing files directly. Expose a function to write files, if the logic happens to be non-trivial. When written as a generator function, each file will be another message yielded. The file path configuration won't be required.

Opportunity

Using a generator function will allow the core transformation to be treated as a thread, and a consumer (like the CLI) will gain great abilities like pause and resume execution at will. This may be used to make the generation interactive or quiet, or expose some user hooks.

Consider improving penpot-export CLI

Description

penpot-export has a single CLI command with no options, penpot-export.

It always requires a user configuration file to work.

Expected output

Consider adding a parameter to provide an alternative user configuration file. E.g. penpot-export -c ../my-other-project/penpot-export.config

Consider improving the user experience by providing a way to execute simple cases with only commands and no configuration file. E.g. penpot-export -h https://my-instance.penpot/ -t $AUTH_TOKEN typographies -f $PENPOT_FILE_UUID -o src/styles/typographies.css

Resources

commander, for usual CLI command options: https://www.npmjs.com/package/commander (autogenerates help commands!)

inquirer, for an interactive CLI program (a configuration generator?): https://www.npmjs.com/package/inquirer 

Fix ES modules interoperability in penpot-export

Description

Currently, a node.js project that declares "type": "module" in the package.json can't use penpot-export with a configuration file.

$ penpot-export
/Users/redradix/Taller/kaleidos-easyfest/penpot-export/packages/cli/dist/bin/index.js:16
var config = require(configFilePath);
             ^

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/redradix/Taller/kaleidos-easyfest/easyfest/frontend/penpot-export.config.js from /Users/redradix/Taller/kaleidos-easyfest/penpot-export/packages/cli/dist/bin/index.js not supported.
penpot-export.config.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead rename penpot-export.config.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /Users/redradix/Taller/kaleidos-easyfest/easyfest/frontend/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).

    at Object.<anonymous> (/Users/redradix/Taller/kaleidos-easyfest/penpot-export/packages/cli/dist/bin/index.js:16:14) {
  code: 'ERR_REQUIRE_ESM'
}

Node.js v18.16.1

This is due to node.js require() interpreting that the .js file is an ES module, even though it's not.

Renaming the configuration file with the .cjs extension won't work, because penpot-export is limited to the exact name of that config. Also, actually writing an ES module in penpot-export.config.js won't work either; it's an issue with the loader.

Workaround

There's a workaround for UNIX systems: 

$ mv penpot-export.config.js penpot-export.config.cjs
$ ln -s penpot-export.config.cjs penpot-export.config.js

Expected outcome

penpot-export is able to read configuration files written as CommonJS in a ES modules project, or written as ES module in a CommonJS project.

Opportunity

Consider implementing a more flexible configuration system with cosmicconfig (used by Prettier): https://github.com/cosmiconfig/cosmiconfig

This could be an opportunity to implement a CLI option to load configuration files other that penpot-export.config.js.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.