penframe
Version:
A lightweight DSL-based wireframe and UI structure visualization tool.
341 lines (253 loc) • 7.78 kB
Markdown
# PenFrame
[](https://badge.fury.io/js/penframe)
[](https://opensource.org/licenses/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
```bash
npm install -g penframe
```
### From Source
```bash
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
```bash
# 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
```bash
npm run build
```
### Run Tests
```bash
npm test
```
### Parse DSL File
```bash
npm start -- examples/sample.pf
```
### Convert AST to SVG
```bash
node src/svg/ast2svg.js examples/ast_sample.json output.svg
```
### Convert AST to PNG
```bash
node src/ast2png.js examples/ast_sample.json output.png --width 800 --scale 2
```
## API Usage
### Module Import (for VScode extensions, etc.)
```javascript
// 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
```javascript
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)
```javascript
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:
```javascript
// 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
````markdown
```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
```html
<!-- 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:
```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:
```bash
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](LICENSE) file for details.
## Links
- [GitHub Repository](https://github.com/ai-program/penframe)
- [npm Package](https://www.npmjs.com/package/penframe)
- [Issues](https://github.com/ai-program/penframe/issues)