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

penframe

v0.3.0

Published

A lightweight DSL-based wireframe and UI structure visualization tool.

Readme

PenFrame

npm version License: MIT

A lightweight DSL-based wireframe and UI structure visualization tool. ✏️ Powered by PenFrame syntax.

PenFrameは、シンプルなDSL(Domain Specific Language)を使ってワイヤーフレームやUI構造を記述し、SVG形式で可視化できるツールです。

Installation

NPM Package

npm install -g penframe

From Source

git clone https://github.com/ai-program/penframe.git
cd penframe
npm install
npm run build

Quick Start

1. Create a PenFrame file

Create a file with .pf extension:

@app { width: 1200, height: 600, title: "My App" }
@headline "Welcome" { level: 1, color: "#333" }
@hr
@p "Welcome to our app!" { align: "center" }
@button "Get Started" { color: "#007bff", textColor: "#ffffff" }
@tabs { items: ["Home", "Features", "Contact"], active: 0 }
@badge "New" { color: "#e74c3c" }

2. Generate SVG and PNG

# Parse DSL to JSON AST
penframe input.pf

# Generate SVG 
penframe input.pf --svg output.svg

# Generate PNG (using Puppeteer for high quality)
penframe input.pf --png output.png

# PNG with custom size and high DPI
penframe input.pf --png output.png --width 1000 --scale 2

# PNG with custom background
penframe input.pf --png output.png --background transparent

# Convert AST JSON to PNG
node src/ast2png.js examples/ast_sample.json output.png --width 800 --scale 3

Supported Elements

PenFrame supports the following UI elements:

Basic Elements

  • @headline "Text" - Page headlines
  • @p "Text" - Text paragraphs
  • @button "Text" - Interactive buttons
  • @hr - Horizontal dividers

Layout Elements

  • @container {...} - Container blocks
  • @tabs { items: ["Tab1", "Tab2"] } - Tab navigation
  • @table [[...]] - Data tables

Form Elements

  • @formcontrol "label" { control: "textbox" } - Input fields
  • @list { items: ["Item1", "Item2"] } - Lists

Media & Indicators

  • @image { url: "path" } - Images
  • @badge "Text" - Status badges

Configuration

Each element supports configuration options:

@button "Submit" {
  color: "#28a745",
  textColor: "#ffffff", 
  width: 120,
  height: 40
}

@tabs { 
  items: ["Home", "Profile", "Settings"],
  active: 0,
  width: 300
}

@badge "New" {
  color: "#dc3545",
  borderRadius: 8
}

Project Structure

  • src/parser/grammar.pegjs - PEG.js grammar definition
  • dist/parser.js - Built parser (generated)
  • src/svg/astToSvg.js - AST to SVG converter
  • src/svg/astToPng.js - AST to PNG converter (Puppeteer)
  • src/cli.js - Command line interface
  • examples/ - Sample files and AST examples
  • docs/ - Documentation

Development

Build Parser

npm run build

Run Tests

npm test

Parse DSL File

npm start -- examples/sample.pf

Convert AST to SVG

node src/svg/ast2svg.js examples/ast_sample.json output.svg

Convert AST to PNG

node src/ast2png.js examples/ast_sample.json output.png --width 800 --scale 2

API Usage

Module Import (for VScode extensions, etc.)

// ES6 import (recommended for modern projects)
import { penframeToSvg, penframeToPng, parse } from 'penframe';

// CommonJS require
const { penframeToSvg, penframeToPng, parse } = require('penframe');

Direct DSL to SVG/PNG Conversion

const { penframeToSvg, penframeToPng, penframeToPngFile } = require('penframe');
const fs = require('fs');

const dslCode = `
@headline "Hello World" { level: 1, color: "#333" }
@button "Click Me" { color: "#007bff", textColor: "#ffffff" }
@badge "New" { color: "#e74c3c" }
`;

// Convert to SVG
const svg = penframeToSvg(dslCode);
fs.writeFileSync('output.svg', svg);

// Convert to PNG buffer (for in-memory use)
const pngBuffer = await penframeToPng(dslCode, { 
  width: 800, 
  deviceScaleFactor: 2,
  background: 'white'
});

// Convert to PNG file
await penframeToPngFile(dslCode, 'output.png', { 
  width: 800, 
  height: 600, 
  deviceScaleFactor: 2 
});

Lower-level API (AST-based)

const { parse, astToSvg, astToPngFile } = require('penframe');

const dslCode = fs.readFileSync('input.pf', 'utf8');
const ast = parse(dslCode);
console.log(JSON.stringify(ast, null, 2));

const svg = astToSvg(ast);
fs.writeFileSync('output.svg', svg);

await astToPngFile(ast, 'output.png', { 
  width: 800, 
  height: 600, 
  deviceScaleFactor: 2 
});

VSCode Extension Usage

For VSCode extensions (like Mermaid preview), you can use PenFrame as follows:

// In your VSCode extension
import { penframeToSvg } from 'penframe';

// Get PenFrame DSL from markdown code block
const penframeDsl = `
@app { width: 800, height: 400, title: "My Wireframe" }
@headline "Dashboard" { level: 1 }
@tabs { items: ["Overview", "Analytics", "Settings"], active: 0 }
@button "Save Changes" { color: "#28a745" }
`;

// Convert to SVG for preview
const svgContent = penframeToSvg(penframeDsl);

// Display in webview
webviewPanel.webview.html = `
<!DOCTYPE html>
<html>
<body>
  ${svgContent}
</body>
</html>
`;

Example Markdown Integration

```penframe
@app { width: 600, height: 300 }
@headline "Login Form" { level: 2 }
@formcontrol "Username" { control: "textbox" }
@formcontrol "Password" { control: "textbox" }
@button "Login" { color: "#007bff" }
```

Browser Usage

PenFrame can also be used directly in browsers via CDN or by downloading the minified file.

CDN Usage

<!-- Include PenFrame from CDN -->
<script src="https://unpkg.com/penframe@latest/dist/penframe.min.js"></script>

<script>
  // Parse DSL
  const dslCode = `
    @app { width: 600, height: 300, title: "My App" }
    @headline "Hello Browser!" { level: 1 }
    @button "Click Me" { color: "#007bff" }
  `;
  
  // Generate SVG
  const svg = PenFrame.penframeToSvg(dslCode);
  document.body.innerHTML = svg;
  
  // Generate PNG Data URL
  PenFrame.penframeToPngDataURL(dslCode, { 
    width: 600, 
    height: 400, 
    scale: 2 
  }).then(dataURL => {
    const img = document.createElement('img');
    img.src = dataURL;
    document.body.appendChild(img);
  });
</script>

Local File Usage

  1. Download penframe.min.js from the releases
  2. Include it in your HTML:
<script src="./penframe.min.js"></script>
<script>
  // Use PenFrame global object
  const svg = PenFrame.penframeToSvg('@headline "Hello!" { level: 1 }');
</script>

Browser API

The browser version provides:

  • PenFrame.parse(dslCode) - Parse DSL to AST
  • PenFrame.penframeToSvg(dslCode) - Convert DSL to SVG
  • PenFrame.penframeToPngDataURL(dslCode, options) - Convert to PNG Data URL
  • PenFrame.penframeToPngBlob(dslCode, options) - Convert to PNG Blob

Note: Browser version uses Canvas API for PNG generation instead of Puppeteer.

Live Demo

Check out the live demo at examples/browser-demo.html after building:

npm run build:browser
# Open examples/browser-demo.html in your browser

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Links