Pulsar and Blueprints
Last updated
Was this helpful?
Last updated
Was this helpful?
Blueprints are the meat of the exporter. You can think about them as templates, similar to or . However, compared to those two templating engines, Pulsar templates are oriented and specifically tailored to help you with code generation and communication with the design system.
In fact, in order to even enable something like this, we wrote our own programming language that you will be using, that shares the syntax with handlebars - but has capabilities more similar to actual programming language. If you ever used any templating language, you will immediately know how to use it. And if not, it is dead easy to start writing it.
Of course, if you want to resort to something you already know and love, Pulsar has an in-built extension model so you can use as well.
But as you will soon learn, there is no need to do things harder than they have to be :)
Pulsar is code-generation-oriented programming/templating language that allows you to communicate with your design systems, get specific data out of it in a unified fashion, and export them in any form or shape you want. Pulsar and Javascript power all exporter packages you can find in the .
Let's see how one such template could look like:
The template is taken from Supernova's Flutter exporter and takes care of the generation of Flutter color definitions. For example, the output of this blueprint can look like this:
Pulsar combines powerful computing functionality and all you would expect from a normal programming language (such as loops, conditions, and so on) but also combines it with the ability to immediately put the result of your computation to good use - outputting it to generated code files.
For example, compare the following:
In the example, we are using the previously shown blueprint to generate colors from design system "Magic Wand" from "General Magic" workspace. However, if we switch to the different design system:
Blueprints define both static and dynamic content - static content will always be the same, while dynamic content depends on the data coming from design systems. Consider the previous blueprint to generate dart color definitions and dissect it:
First, we declare the static part that will always be output into a generated file:
You can immediately tell it is a static part of the generated output because it is not contained within dynamic execution tags, {{ }}
and {[ /]}
. Anything that is not contained is always considered output.
Next, we ask the design system to give us all data we are interested in - in this case, we ask for a specific set of design tokens, tokenized colors, and define a new property to store this data into:
Finally, we iterate each token we have obtained and generate a color definition for each:
You are probably wondering how did we obtain the color definition from the token if there is no code that does this? Blueprints can be used inside each other, so we have defined a separate blueprint called export_color
to provide this shared functionality (color conversion in case of the Flutter exporter is used on multiple places - for shadows, gradients, and so on):
Because the color is defined as a RGBA colorValue
but Flutter expects a different format (ARGB), we are just splitting it up and reformatting it so it fits the needs of the platform better. This blueprint can be then used everywhere we need it.
Combined all together, tokens or any other elements of the design system can be represented in any form or shape, limited just by your imagination.
Wondering how did we get the color definitions here? This is because the Pulsar core functions you use when developing the blueprint know about your design system selection from either the VSCode, or the CI when you are running through hooks.
You can see that the output is completely different! The exporter package and debugging runtime always target a specific combination of workspace / design system / version. If you publish your exporter to , then the completely same code we just executed twice with different targets can be used by others to run against their design system as well.
There are dozens of functions you can use to ask for the design system data. If you want to learn all about what is available, see the description of our
Keen to learn everything about the language syntax and options? Refer to our to understand it in detail.
You could argue that converting the values using the blueprint is a bit cumbersome. For this reason, it is also possible to , bringing together a powerful templating language with the most-used computing and scripting language for an uber-powerful combination.