penframe
Version:
A lightweight DSL-based wireframe and UI structure visualization tool.
171 lines (149 loc) • 4.33 kB
JavaScript
const puppeteer = require('puppeteer');
const astToSvg = require('./astToSvg');
/**
* Convert SVG text to PNG using Puppeteer
* @param {string} svgText - SVG content as string
* @param {string} outputPath - Output PNG file path
* @param {Object} options - Screenshot options
* @param {number} options.width - Viewport width (optional)
* @param {number} options.height - Viewport height (optional)
* @param {number} options.deviceScaleFactor - Device scale factor for high DPI (default: 2)
* @param {string} options.background - Background color (default: 'white')
*/
async function renderPNGFromSVG(svgText, outputPath, options = {}) {
const {
width,
height,
deviceScaleFactor = 2, // Higher DPI for better quality
background = 'white'
} = options;
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
try {
const page = await browser.newPage();
// Set viewport if dimensions specified
if (width && height) {
await page.setViewport({
width,
height,
deviceScaleFactor
});
}
// Create HTML content with SVG
const htmlContent = `
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
padding: 20px;
background-color: ${background};
display: flex;
justify-content: center;
align-items: flex-start;
}
svg {
max-width: 100%;
height: auto;
}
</style>
</head>
<body>${svgText}</body>
</html>
`;
await page.setContent(htmlContent, { waitUntil: 'networkidle0' });
// Find SVG element and take screenshot
const svgElement = await page.$('svg');
if (!svgElement) {
throw new Error('SVG element not found in the rendered content');
}
await svgElement.screenshot({
path: outputPath,
omitBackground: background === 'transparent'
});
} finally {
await browser.close();
}
}
/**
* Convert AST to PNG using Puppeteer
* @param {Object} ast - The AST object
* @param {string} outputPath - Output PNG file path
* @param {Object} options - Conversion options
*/
async function astToPngFile(ast, outputPath, options = {}) {
// Convert AST to SVG
const svgContent = astToSvg(ast);
// Convert SVG to PNG using Puppeteer
await renderPNGFromSVG(svgContent, outputPath, options);
}
/**
* Convert AST to PNG buffer using Puppeteer
* @param {Object} ast - The AST object
* @param {Object} options - Conversion options
* @returns {Promise<Buffer>} PNG buffer
*/
async function astToPng(ast, options = {}) {
const {
width,
height,
deviceScaleFactor = 2,
background = 'white'
} = options;
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
try {
const page = await browser.newPage();
if (width && height) {
await page.setViewport({
width,
height,
deviceScaleFactor
});
}
const svgContent = astToSvg(ast);
const htmlContent = `
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
padding: 20px;
background-color: ${background};
display: flex;
justify-content: center;
align-items: flex-start;
}
svg {
max-width: 100%;
height: auto;
}
</style>
</head>
<body>${svgContent}</body>
</html>
`;
await page.setContent(htmlContent, { waitUntil: 'networkidle0' });
const svgElement = await page.$('svg');
if (!svgElement) {
throw new Error('SVG element not found in the rendered content');
}
const buffer = await svgElement.screenshot({
omitBackground: background === 'transparent'
});
return buffer;
} finally {
await browser.close();
}
}
module.exports = {
renderPNGFromSVG,
astToPng,
astToPngFile
};