Initial commit
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Diagram Capture Script
|
||||
* Converts HTML diagrams to high-resolution PNGs using Playwright
|
||||
*
|
||||
* Usage:
|
||||
* node capture-diagrams.js [html-file] [output-png]
|
||||
* node capture-diagrams.js # Captures all diagrams in current directory
|
||||
*
|
||||
* Prerequisites:
|
||||
* npm install playwright
|
||||
* npx playwright install chromium
|
||||
*/
|
||||
|
||||
const { chromium } = require('playwright');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
// Configuration
|
||||
const CONFIG = {
|
||||
deviceScaleFactor: 2, // 2x for retina quality
|
||||
selector: '.diagram-container', // Default container selector
|
||||
};
|
||||
|
||||
/**
|
||||
* Capture a single HTML file to PNG
|
||||
*/
|
||||
async function captureScreenshot(htmlPath, pngPath, selector = CONFIG.selector) {
|
||||
const browser = await chromium.launch();
|
||||
const context = await browser.newContext({
|
||||
deviceScaleFactor: CONFIG.deviceScaleFactor,
|
||||
});
|
||||
const page = await context.newPage();
|
||||
|
||||
const absoluteHtmlPath = path.resolve(htmlPath);
|
||||
console.log(`Capturing ${htmlPath}...`);
|
||||
|
||||
await page.goto(`file://${absoluteHtmlPath}`);
|
||||
|
||||
const element = await page.locator(selector);
|
||||
await element.screenshot({
|
||||
path: pngPath,
|
||||
type: 'png',
|
||||
});
|
||||
|
||||
console.log(` → Saved to ${pngPath}`);
|
||||
await browser.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture all HTML diagrams in a directory
|
||||
*/
|
||||
async function captureAllDiagrams(directory = '.') {
|
||||
const browser = await chromium.launch();
|
||||
const context = await browser.newContext({
|
||||
deviceScaleFactor: CONFIG.deviceScaleFactor,
|
||||
});
|
||||
const page = await context.newPage();
|
||||
|
||||
// Find all *_diagram*.html files
|
||||
const files = fs.readdirSync(directory)
|
||||
.filter(f => f.endsWith('.html') && f.includes('diagram'));
|
||||
|
||||
if (files.length === 0) {
|
||||
console.log('No diagram HTML files found in directory');
|
||||
await browser.close();
|
||||
return;
|
||||
}
|
||||
|
||||
for (const htmlFile of files) {
|
||||
const htmlPath = path.join(directory, htmlFile);
|
||||
const pngPath = htmlPath.replace('.html', '.png');
|
||||
|
||||
console.log(`Capturing ${htmlFile}...`);
|
||||
await page.goto(`file://${path.resolve(htmlPath)}`);
|
||||
|
||||
try {
|
||||
const element = await page.locator(CONFIG.selector);
|
||||
await element.screenshot({ path: pngPath, type: 'png' });
|
||||
console.log(` → Saved to ${path.basename(pngPath)}`);
|
||||
} catch (error) {
|
||||
console.log(` ✗ Failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
await browser.close();
|
||||
console.log('\nAll diagrams captured successfully!');
|
||||
}
|
||||
|
||||
// Main execution
|
||||
async function main() {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
if (args.length === 2) {
|
||||
// Single file mode: node capture-diagrams.js input.html output.png
|
||||
await captureScreenshot(args[0], args[1]);
|
||||
} else if (args.length === 1) {
|
||||
// Directory mode: node capture-diagrams.js ./docs
|
||||
await captureAllDiagrams(args[0]);
|
||||
} else {
|
||||
// Default: capture all diagrams in current directory
|
||||
await captureAllDiagrams('.');
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,164 @@
|
||||
/* Academic PDF Style Template
|
||||
* For use with pandoc + weasyprint
|
||||
* Based on: paralleLLM empathy-experiment-v1.0.pdf
|
||||
*/
|
||||
|
||||
/* ==========================================================================
|
||||
Base Typography
|
||||
========================================================================== */
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Tables (Academic Style)
|
||||
========================================================================== */
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1em 0;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
table th, table td {
|
||||
padding: 0.5em 0.75em;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* Academic-style borders: top/bottom on header, bottom on last row */
|
||||
table thead th {
|
||||
border-top: 2px solid #000;
|
||||
border-bottom: 2px solid #000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table tbody td {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
table tbody tr:last-child td {
|
||||
border-bottom: 2px solid #000;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Block Elements
|
||||
========================================================================== */
|
||||
|
||||
blockquote {
|
||||
border-left: 4px solid #ddd;
|
||||
margin: 1em 0;
|
||||
padding-left: 1em;
|
||||
color: #555;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
code {
|
||||
background: #f5f5f5;
|
||||
padding: 0.2em 0.4em;
|
||||
border-radius: 3px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #f5f5f5;
|
||||
padding: 1em;
|
||||
border-radius: 5px;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
pre code {
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 2em 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Figures and Images
|
||||
========================================================================== */
|
||||
|
||||
figure {
|
||||
page-break-inside: avoid;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
|
||||
figure img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
margin-top: 0.5em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Page Control (Print/PDF)
|
||||
========================================================================== */
|
||||
|
||||
@page {
|
||||
margin: 2cm;
|
||||
}
|
||||
|
||||
/* Keep headings with following content */
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
|
||||
/* Prevent orphan paragraphs */
|
||||
p {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
|
||||
/* Keep lists together when possible */
|
||||
ul, ol {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Utility Classes
|
||||
========================================================================== */
|
||||
|
||||
/* For centered figures in weasyprint */
|
||||
.figure-centered {
|
||||
margin: 2em auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.figure-centered img {
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Small text for appendix tables */
|
||||
.small-text {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
Reference in New Issue
Block a user