npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lit-pigeon/import-unlayer

v0.2.0

Published

Unlayer design-JSON to PigeonDocument importer for Lit Pigeon — migrate off Unlayer without rebuilding your templates

Readme

@lit-pigeon/import-unlayer

Import an Unlayer design JSON into a Lit Pigeon PigeonDocument — migrate existing templates instead of rebuilding them.

Pairs with @lit-pigeon/parser-mjml (MJML → document) and @lit-pigeon/figma-import (Figma frame → document).

Install

npm install @lit-pigeon/import-unlayer

Usage

Feed it whatever editor.saveDesign() gave you — the parsed object or the raw JSON string:

import { unlayerToDocument } from '@lit-pigeon/import-unlayer';

const { document, warnings } = unlayerToDocument(design);

for (const warning of warnings) {
  console.warn(`[${warning.code}] ${warning.message}`);
}

Then render it, or load it straight into the editor:

import { documentToMjml } from '@lit-pigeon/renderer-mjml';

const mjml = documentToMjml(document);

Options

| Option | Default | Description | | --- | --- | --- | | name | 'Imported from Unlayer' | Name for the imported template. |

What gets imported

| Unlayer | Lit Pigeon | Notes | | --- | --- | --- | | text | text | Block-level font size and colour are inlined (see below). | | heading | text | Wrapped in its <h1>–<h3> tag; h4–h6 clamp to h3. | | image | image | Link, alt text, explicit and auto widths. | | button | button | Colours, radius, inner/outer padding. size.autoWidth inverts to fullWidth. | | divider | divider | Border colour, width, and style. | | html | html | Passed through verbatim. | | menu | navbar | Items, alignment, link colour and size. | | social | social | Known platforms map by name; anything else becomes a custom icon. | | rows / cells | rows / columnRatios | Relative widths convert to the 12-column grid ([1, 2] → [4, 8]). | | body values | body attributes | Width, background, font family, alignment, preheader. |

Why colours end up in a <span>

Unlayer stores font size and colour on the content block. A Lit Pigeon TextBlock only carries content, padding, lineHeight and textAlign, so dropping them would lose the design — a template with textColor: #ffffff on a black body would import as black-on-black.

The importer pushes that typography into the HTML instead. The editor's rich-text sanitiser keeps style on <span> only, and only for color, font-family and font-size, so the styling wraps the inner content of each top-level element:

<!-- Unlayer: { text: "<p>Hi</p>", color: "#ffffff", fontSize: "17px" } -->
<p><span style="color: #ffffff; font-size: 17px">Hi</span></p>

What does not survive

Import is best-effort and never throws. Anything that cannot be represented is dropped and reported in warnings, so a migration UI can tell the user exactly what needs a second look.

| Code | Meaning | | --- | --- | | not-a-design | Input was not valid JSON, or had no body key. | | unsupported-block | An Unlayer block with no Pigeon equivalent (video, timer, form). | | custom-tool | A custom#* tool. Re-create it as a Lit Pigeon plugin block. | | display-condition-dropped | See below. | | heading-level-clamped | h4–h6 imported as h3. | | empty-row | A row with no columns was skipped. | | no-rows | The design had no rows at all. |

Display conditions are dropped deliberately. Unlayer stores them as raw before/after template fragments, not as the boolean expression Pigeon's condition wraps in {{#if}}. Guessing a translation would silently change who receives the content, so the importer reports the condition by name and leaves the row unconditional for you to re-add.

Mobile _override values and hideDesktop / hideMobile are not yet mapped.

Licence

MIT