mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-14 18:44:05 +02:00
Add frontend autoformatting and set CI to require formatted code for all languages (#6052)
# Description of Changes Changes the strategy for autoformatting to reject PRs if they are not formatted correctly instead of allowing them to merge and then spawning a new PR to fix the formatting. The old strategy just caused more work for us because we'd have to manually approve the followup PR and get it merged, which required 2 reviewers so in practice it rarely got done and just meant everyone's PRs ended up containing reformatting for unrelated files, which makes code review unnecessarily difficult. If the PR's code is not formatted correctly after this PR, a comment will be added automatically to tell the author how to run the formatter script to fix their code so it can go in. This also enables autoformatting for the frontend code, using Prettier. I've enabled it for pretty much everything in the frontend folder, other than 3rd party files and files it doesn't make sense for. I also excluded Markdown because it sounds likely to be more annoying to have to autoformat the Markdown in the frontend folder but nowhere else. Open to changing this though if people disagree. > [!note] > > Advice to reviewers: The first commit contains all of the actual logic I've introduced (CI changes, Prettier config, etc.) > The second commit is just the reformatting of the entire frontend folder. > The first commit needs proper review, the second one just give it a spot-check that it's doing what you'd expect.
This commit is contained in:
@@ -8,20 +8,20 @@
|
||||
* for users to experiment with Stirling PDF's features.
|
||||
*/
|
||||
|
||||
import puppeteer from 'puppeteer';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname, join } from 'path';
|
||||
import { existsSync, mkdirSync, statSync } from 'fs';
|
||||
import puppeteer from "puppeteer";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname, join } from "path";
|
||||
import { existsSync, mkdirSync, statSync } from "fs";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const TEMPLATE_PATH = join(__dirname, 'template.html');
|
||||
const OUTPUT_DIR = join(__dirname, '../../public/samples');
|
||||
const OUTPUT_PATH = join(OUTPUT_DIR, 'Sample.pdf');
|
||||
const TEMPLATE_PATH = join(__dirname, "template.html");
|
||||
const OUTPUT_DIR = join(__dirname, "../../public/samples");
|
||||
const OUTPUT_PATH = join(OUTPUT_DIR, "Sample.pdf");
|
||||
|
||||
async function generatePDF() {
|
||||
console.log('🚀 Starting Stirling PDF sample document generation...\n');
|
||||
console.log("🚀 Starting Stirling PDF sample document generation...\n");
|
||||
|
||||
// Ensure output directory exists
|
||||
if (!existsSync(OUTPUT_DIR)) {
|
||||
@@ -40,66 +40,65 @@ async function generatePDF() {
|
||||
let browser;
|
||||
try {
|
||||
// Launch Puppeteer
|
||||
console.log('🌐 Launching browser...');
|
||||
console.log("🌐 Launching browser...");
|
||||
browser = await puppeteer.launch({
|
||||
headless: 'new',
|
||||
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
||||
headless: "new",
|
||||
args: ["--no-sandbox", "--disable-setuid-sandbox"],
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
|
||||
// Set viewport to match A4 proportions
|
||||
await page.setViewport({
|
||||
width: 794, // A4 width in pixels at 96 DPI
|
||||
width: 794, // A4 width in pixels at 96 DPI
|
||||
height: 1123, // A4 height in pixels at 96 DPI
|
||||
deviceScaleFactor: 2 // Higher quality rendering
|
||||
deviceScaleFactor: 2, // Higher quality rendering
|
||||
});
|
||||
|
||||
// Navigate to the template file
|
||||
const fileUrl = `file://${TEMPLATE_PATH}`;
|
||||
console.log('📖 Loading HTML template...');
|
||||
console.log("📖 Loading HTML template...");
|
||||
await page.goto(fileUrl, {
|
||||
waitUntil: 'networkidle0' // Wait for all resources to load
|
||||
waitUntil: "networkidle0", // Wait for all resources to load
|
||||
});
|
||||
|
||||
// Generate PDF with A4 dimensions
|
||||
console.log('📝 Generating PDF...');
|
||||
console.log("📝 Generating PDF...");
|
||||
await page.pdf({
|
||||
path: OUTPUT_PATH,
|
||||
format: 'A4',
|
||||
format: "A4",
|
||||
printBackground: true,
|
||||
margin: {
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0
|
||||
left: 0,
|
||||
},
|
||||
preferCSSPageSize: true
|
||||
preferCSSPageSize: true,
|
||||
});
|
||||
|
||||
console.log('\n✅ PDF generated successfully!');
|
||||
console.log("\n✅ PDF generated successfully!");
|
||||
console.log(`📦 Output: ${OUTPUT_PATH}`);
|
||||
|
||||
// Get file size
|
||||
const stats = statSync(OUTPUT_PATH);
|
||||
const fileSizeInKB = (stats.size / 1024).toFixed(2);
|
||||
console.log(`📊 File size: ${fileSizeInKB} KB`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n❌ Error generating PDF:', error.message);
|
||||
console.error("\n❌ Error generating PDF:", error.message);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
if (browser) {
|
||||
await browser.close();
|
||||
console.log('🔒 Browser closed.');
|
||||
console.log("🔒 Browser closed.");
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n🎉 Done! Sample PDF is ready for use in Stirling PDF.\n');
|
||||
console.log("\n🎉 Done! Sample PDF is ready for use in Stirling PDF.\n");
|
||||
}
|
||||
|
||||
// Run the generator
|
||||
generatePDF().catch(error => {
|
||||
console.error('Fatal error:', error);
|
||||
generatePDF().catch((error) => {
|
||||
console.error("Fatal error:", error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
--color-white: #ffffff;
|
||||
|
||||
/* Font Stack */
|
||||
--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
--font-family:
|
||||
-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
|
||||
"Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
* {
|
||||
|
||||
@@ -1,234 +1,244 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Stirling PDF - Sample Document</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Page 1: Hero / Cover Page -->
|
||||
<div class="page page-1">
|
||||
<div class="decorative-shapes">
|
||||
<img src="../../public/modern-logo/StirlingPDFLogoNoTextLight.svg" class="shape shape-1" alt="">
|
||||
<img src="../../public/modern-logo/StirlingPDFLogoNoTextDark.svg" class="shape shape-2" alt="">
|
||||
<img src="../../public/modern-logo/StirlingPDFLogoNoTextLight.svg" class="shape shape-3" alt="">
|
||||
<img src="../../public/modern-logo/StirlingPDFLogoNoTextDark.svg" class="shape shape-4" alt="">
|
||||
<img src="../../public/modern-logo/StirlingPDFLogoNoTextLight.svg" class="shape shape-5" alt="">
|
||||
</div>
|
||||
<div class="hero-content">
|
||||
<div class="logo-container">
|
||||
<img src="../../public/modern-logo/StirlingPDFLogoWhiteText.svg" alt="Stirling PDF" class="hero-logo">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Stirling PDF - Sample Document</title>
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<!-- Page 1: Hero / Cover Page -->
|
||||
<div class="page page-1">
|
||||
<div class="decorative-shapes">
|
||||
<img src="../../public/modern-logo/StirlingPDFLogoNoTextLight.svg" class="shape shape-1" alt="" />
|
||||
<img src="../../public/modern-logo/StirlingPDFLogoNoTextDark.svg" class="shape shape-2" alt="" />
|
||||
<img src="../../public/modern-logo/StirlingPDFLogoNoTextLight.svg" class="shape shape-3" alt="" />
|
||||
<img src="../../public/modern-logo/StirlingPDFLogoNoTextDark.svg" class="shape shape-4" alt="" />
|
||||
<img src="../../public/modern-logo/StirlingPDFLogoNoTextLight.svg" class="shape shape-5" alt="" />
|
||||
</div>
|
||||
<h1 class="hero-tagline">The Free Adobe Acrobat Alternative</h1>
|
||||
<div class="hero-stats">
|
||||
<div class="stat-badge">
|
||||
<span class="stat-number">10M+</span>
|
||||
<span class="stat-label">Downloads</span>
|
||||
<div class="hero-content">
|
||||
<div class="logo-container">
|
||||
<img src="../../public/modern-logo/StirlingPDFLogoWhiteText.svg" alt="Stirling PDF" class="hero-logo" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="hero-features">
|
||||
<div class="feature-pill">Open Source</div>
|
||||
<div class="feature-pill">Privacy First</div>
|
||||
<div class="feature-pill">Self-Hosted</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Page 2: What is Stirling PDF -->
|
||||
<div class="page page-2">
|
||||
<div class="content-wrapper">
|
||||
<h2 class="page-title">What is Stirling PDF?</h2>
|
||||
<p class="intro-text">
|
||||
Stirling PDF is a robust, web-based PDF manipulation tool.
|
||||
It enables you to carry out various operations on PDF files, including splitting,
|
||||
merging, converting, rearranging, adding images, rotating, compressing, and more.
|
||||
</p>
|
||||
|
||||
<div class="value-props">
|
||||
<div class="value-prop">
|
||||
<div class="value-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" />
|
||||
</svg>
|
||||
<h1 class="hero-tagline">The Free Adobe Acrobat Alternative</h1>
|
||||
<div class="hero-stats">
|
||||
<div class="stat-badge">
|
||||
<span class="stat-number">10M+</span>
|
||||
<span class="stat-label">Downloads</span>
|
||||
</div>
|
||||
<h3>50+ PDF Operations</h3>
|
||||
<p>Comprehensive toolkit covering all your PDF needs. From basic operations to advanced processing.</p>
|
||||
</div>
|
||||
|
||||
<div class="value-prop">
|
||||
<div class="value-icon">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M7.4 17.25q-1.05.875-2.187.8t-1.988-.775t-1.162-1.837t.412-2.338L4.35 10q-.625-.55-.987-1.325T3 7q0-1.65 1.175-2.825T7 3t2.825 1.175T11 7T9.825 9.825T7 11q-.225 0-.45-.025t-.425-.075L4.2 14.15q-.275.45-.175.888t.425.712t.775.313t.875-.313l10.5-9.025q1.05-.875 2.2-.788t2 .788t1.15 1.838t-.425 2.337L19.65 14q.625.55.988 1.325T21 17q0 1.65-1.175 2.825T17 21t-2.825-1.175T13 17t1.175-2.825T17 13q.225 0 .438.025t.412.075l1.95-3.25q.275-.45.175-.888t-.425-.712t-.775-.312t-.875.312zM7 9q.825 0 1.413-.587T9 7t-.587-1.412T7 5t-1.412.588T5 7t.588 1.413T7 9m10 10q.825 0 1.413-.587T19 17t-.587-1.412T17 15t-1.412.588T15 17t.588 1.413T17 19m0-2" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3>Workflow Automation</h3>
|
||||
<p>Chain multiple operations together and save them as reusable workflows. Perfect for recurring tasks.</p>
|
||||
</div>
|
||||
|
||||
<div class="value-prop">
|
||||
<div class="value-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<line x1="2" y1="12" x2="22" y2="12" />
|
||||
<path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3>Multi-Language Support</h3>
|
||||
<p>Available in over 30 languages with community-contributed translations. Accessible to users worldwide.</p>
|
||||
</div>
|
||||
|
||||
<div class="value-prop">
|
||||
<div class="value-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="5" y="11" width="14" height="10" rx="2" />
|
||||
<circle cx="12" cy="16" r="1" />
|
||||
<path d="M8 11V7a4 4 0 0 1 8 0v4" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3>Privacy First</h3>
|
||||
<p>Self-hosted solution means your data stays on your infrastructure. You have full control over your documents.</p>
|
||||
</div>
|
||||
|
||||
<div class="value-prop">
|
||||
<div class="value-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<path d="m9 12 2 2 4-4" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3>Open Source</h3>
|
||||
<p>Transparent, community-driven development. Inspect the code, contribute features, and adapt as needed.</p>
|
||||
</div>
|
||||
|
||||
<div class="value-prop">
|
||||
<div class="value-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="16 18 22 12 16 6" />
|
||||
<polyline points="8 6 2 12 8 18" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3>API Access</h3>
|
||||
<p>RESTful API for integration with external tools and scripts. Automate PDF operations programmatically.</p>
|
||||
<div class="hero-features">
|
||||
<div class="feature-pill">Open Source</div>
|
||||
<div class="feature-pill">Privacy First</div>
|
||||
<div class="feature-pill">Self-Hosted</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Page 3: Key Features -->
|
||||
<div class="page page-3">
|
||||
<div class="content-wrapper">
|
||||
<h2 class="page-title">Key Features</h2>
|
||||
<!-- Page 2: What is Stirling PDF -->
|
||||
<div class="page page-2">
|
||||
<div class="content-wrapper">
|
||||
<h2 class="page-title">What is Stirling PDF?</h2>
|
||||
<p class="intro-text">
|
||||
Stirling PDF is a robust, web-based PDF manipulation tool. It enables you to carry out various operations on PDF
|
||||
files, including splitting, merging, converting, rearranging, adding images, rotating, compressing, and more.
|
||||
</p>
|
||||
|
||||
<div class="features-grid">
|
||||
<div class="feature-card" data-category="general">
|
||||
<div class="feature-header">
|
||||
<div class="feature-icon-large">
|
||||
<div class="value-props">
|
||||
<div class="value-prop">
|
||||
<div class="value-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||||
<polyline points="14 2 14 8 20 8" />
|
||||
<line x1="16" y1="13" x2="8" y2="13" />
|
||||
<line x1="16" y1="17" x2="8" y2="17" />
|
||||
<polyline points="10 9 9 9 8 9" />
|
||||
<path
|
||||
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3>Page Operations</h3>
|
||||
<h3>50+ PDF Operations</h3>
|
||||
<p>Comprehensive toolkit covering all your PDF needs. From basic operations to advanced processing.</p>
|
||||
</div>
|
||||
<ul class="feature-list">
|
||||
<li>Merge & split PDFs</li>
|
||||
<li>Rearrange pages</li>
|
||||
<li>Rotate & crop</li>
|
||||
<li>Extract pages</li>
|
||||
<li>Multi-page layout</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="feature-card" data-category="security">
|
||||
<div class="feature-header">
|
||||
<div class="feature-icon-large">
|
||||
<div class="value-prop">
|
||||
<div class="value-icon">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
d="M7.4 17.25q-1.05.875-2.187.8t-1.988-.775t-1.162-1.837t.412-2.338L4.35 10q-.625-.55-.987-1.325T3 7q0-1.65 1.175-2.825T7 3t2.825 1.175T11 7T9.825 9.825T7 11q-.225 0-.45-.025t-.425-.075L4.2 14.15q-.275.45-.175.888t.425.712t.775.313t.875-.313l10.5-9.025q1.05-.875 2.2-.788t2 .788t1.15 1.838t-.425 2.337L19.65 14q.625.55.988 1.325T21 17q0 1.65-1.175 2.825T17 21t-2.825-1.175T13 17t1.175-2.825T17 13q.225 0 .438.025t.412.075l1.95-3.25q.275-.45.175-.888t-.425-.712t-.775-.312t-.875.312zM7 9q.825 0 1.413-.587T9 7t-.587-1.412T7 5t-1.412.588T5 7t.588 1.413T7 9m10 10q.825 0 1.413-.587T19 17t-.587-1.412T17 15t-1.412.588T15 17t.588 1.413T17 19m0-2"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3>Workflow Automation</h3>
|
||||
<p>Chain multiple operations together and save them as reusable workflows. Perfect for recurring tasks.</p>
|
||||
</div>
|
||||
|
||||
<div class="value-prop">
|
||||
<div class="value-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
|
||||
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<line x1="2" y1="12" x2="22" y2="12" />
|
||||
<path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3>Security & Signing</h3>
|
||||
<h3>Multi-Language Support</h3>
|
||||
<p>Available in over 30 languages with community-contributed translations. Accessible to users worldwide.</p>
|
||||
</div>
|
||||
<ul class="feature-list">
|
||||
<li>Password protection</li>
|
||||
<li>Digital signatures</li>
|
||||
<li>Watermarks</li>
|
||||
<li>Permission controls</li>
|
||||
<li>Redaction tools</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="feature-card" data-category="formatting">
|
||||
<div class="feature-header">
|
||||
<div class="feature-icon-large">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="m5.825 17l1.9 1.9q.3.3.288.7t-.313.7q-.3.275-.7.288t-.7-.288l-3.6-3.6q-.15-.15-.213-.325T2.426 16t.063-.375t.212-.325l3.6-3.6q.275-.275.688-.275t.712.275q.3.3.3.713t-.3.712L5.825 15H20q.425 0 .713.288T21 16t-.288.713T20 17zm12.35-8H4q-.425 0-.712-.288T3 8t.288-.712T4 7h14.175l-1.9-1.9q-.3-.3-.287-.7t.312-.7q.3-.275.7-.288t.7.288l3.6 3.6q.15.15.213.325t.062.375t-.062.375t-.213.325l-3.6 3.6q-.275.275-.687.275T16.3 12.3q-.3-.3-.3-.712t.3-.713z" />
|
||||
<div class="value-prop">
|
||||
<div class="value-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="5" y="11" width="14" height="10" rx="2" />
|
||||
<circle cx="12" cy="16" r="1" />
|
||||
<path d="M8 11V7a4 4 0 0 1 8 0v4" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3>File Conversions</h3>
|
||||
<h3>Privacy First</h3>
|
||||
<p>
|
||||
Self-hosted solution means your data stays on your infrastructure. You have full control over your documents.
|
||||
</p>
|
||||
</div>
|
||||
<ul class="feature-list">
|
||||
<li>PDF to/from images</li>
|
||||
<li>Office documents</li>
|
||||
<li>HTML to PDF</li>
|
||||
<li>Markdown to PDF</li>
|
||||
<li>PDF to Word/Excel</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="feature-card" data-category="automation">
|
||||
<div class="feature-header">
|
||||
<div class="feature-icon-large">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M7.4 17.25q-1.05.875-2.187.8t-1.988-.775t-1.162-1.837t.412-2.338L4.35 10q-.625-.55-.987-1.325T3 7q0-1.65 1.175-2.825T7 3t2.825 1.175T11 7T9.825 9.825T7 11q-.225 0-.45-.025t-.425-.075L4.2 14.15q-.275.45-.175.888t.425.712t.775.313t.875-.313l10.5-9.025q1.05-.875 2.2-.788t2 .788t1.15 1.838t-.425 2.337L19.65 14q.625.55.988 1.325T21 17q0 1.65-1.175 2.825T17 21t-2.825-1.175T13 17t1.175-2.825T17 13q.225 0 .438.025t.412.075l1.95-3.25q.275-.45.175-.888t-.425-.712t-.775-.312t-.875.312zM7 9q.825 0 1.413-.587T9 7t-.587-1.412T7 5t-1.412.588T5 7t.588 1.413T7 9m10 10q.825 0 1.413-.587T19 17t-.587-1.412T17 15t-1.412.588T15 17t.588 1.413T17 19m0-2" />
|
||||
<div class="value-prop">
|
||||
<div class="value-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<path d="m9 12 2 2 4-4" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3>Automation</h3>
|
||||
<h3>Open Source</h3>
|
||||
<p>Transparent, community-driven development. Inspect the code, contribute features, and adapt as needed.</p>
|
||||
</div>
|
||||
<ul class="feature-list">
|
||||
<li>Multi-step workflows</li>
|
||||
<li>Chain PDF operations</li>
|
||||
<li>Save recurring tasks</li>
|
||||
<li>Batch file processing</li>
|
||||
<li>API integration</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="additional-features">
|
||||
<div class="additional-features-header">
|
||||
<div class="additional-features-icon">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M6 20q-.825 0-1.4125-.5875T4 18t.5875-1.4125T6 16t1.4125.5875T8 18t-.5875 1.4125T6 20m6 0q-.825 0-1.4125-.5875T10 18t.5875-1.4125T12 16t1.4125.5875T14 18t-.5875 1.4125T12 20m6 0q-.825 0-1.4125-.5875T16 18t.5875-1.4125T18 16t1.4125.5875T20 18t-.5875 1.4125T18 20M6 14q-.825 0-1.4125-.5875T4 12t.5875-1.4125T6 10t1.4125.5875T8 12t-.5875 1.4125T6 14m6 0q-.825 0-1.4125-.5875T10 12t.5875-1.4125T12 10t1.4125.5875T14 12t-.5875 1.4125T12 14m6 0q-.825 0-1.4125-.5875T16 12t.5875-1.4125T18 10t1.4125.5875T20 12t-.5875 1.4125T18 14M6 8q-.825 0-1.4125-.5875T4 6t.5875-1.4125T6 4t1.4125.5875T8 6t-.5875 1.4125T6 8m6 0q-.825 0-1.4125-.5875T10 6t.5875-1.4125T12 4t1.4125.5875T14 6t-.5875 1.4125T12 8m6 0q-.825 0-1.4125-.5875T16 6t.5875-1.4125T18 4t1.4125.5875T20 6t-.5875 1.4125T18 8" />
|
||||
</svg>
|
||||
<div class="value-prop">
|
||||
<div class="value-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="16 18 22 12 16 6" />
|
||||
<polyline points="8 6 2 12 8 18" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3>API Access</h3>
|
||||
<p>RESTful API for integration with external tools and scripts. Automate PDF operations programmatically.</p>
|
||||
</div>
|
||||
<h3>Plus Many More</h3>
|
||||
</div>
|
||||
<div class="additional-features-grid">
|
||||
<ul>
|
||||
<li>OCR text recognition</li>
|
||||
<li>Compress PDFs</li>
|
||||
<li>Add images & stamps</li>
|
||||
<li>Detect blank pages</li>
|
||||
<li>Extract images</li>
|
||||
<li>Edit metadata</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>Flatten forms</li>
|
||||
<li>PDF/A conversion</li>
|
||||
<li>Add page numbers</li>
|
||||
<li>Remove pages</li>
|
||||
<li>Repair PDFs</li>
|
||||
<li>And 40+ more tools</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
<!-- Page 3: Key Features -->
|
||||
<div class="page page-3">
|
||||
<div class="content-wrapper">
|
||||
<h2 class="page-title">Key Features</h2>
|
||||
|
||||
<div class="features-grid">
|
||||
<div class="feature-card" data-category="general">
|
||||
<div class="feature-header">
|
||||
<div class="feature-icon-large">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||||
<polyline points="14 2 14 8 20 8" />
|
||||
<line x1="16" y1="13" x2="8" y2="13" />
|
||||
<line x1="16" y1="17" x2="8" y2="17" />
|
||||
<polyline points="10 9 9 9 8 9" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3>Page Operations</h3>
|
||||
</div>
|
||||
<ul class="feature-list">
|
||||
<li>Merge & split PDFs</li>
|
||||
<li>Rearrange pages</li>
|
||||
<li>Rotate & crop</li>
|
||||
<li>Extract pages</li>
|
||||
<li>Multi-page layout</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="feature-card" data-category="security">
|
||||
<div class="feature-header">
|
||||
<div class="feature-icon-large">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
|
||||
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3>Security & Signing</h3>
|
||||
</div>
|
||||
<ul class="feature-list">
|
||||
<li>Password protection</li>
|
||||
<li>Digital signatures</li>
|
||||
<li>Watermarks</li>
|
||||
<li>Permission controls</li>
|
||||
<li>Redaction tools</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="feature-card" data-category="formatting">
|
||||
<div class="feature-header">
|
||||
<div class="feature-icon-large">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
d="m5.825 17l1.9 1.9q.3.3.288.7t-.313.7q-.3.275-.7.288t-.7-.288l-3.6-3.6q-.15-.15-.213-.325T2.426 16t.063-.375t.212-.325l3.6-3.6q.275-.275.688-.275t.712.275q.3.3.3.713t-.3.712L5.825 15H20q.425 0 .713.288T21 16t-.288.713T20 17zm12.35-8H4q-.425 0-.712-.288T3 8t.288-.712T4 7h14.175l-1.9-1.9q-.3-.3-.287-.7t.312-.7q.3-.275.7-.288t.7.288l3.6 3.6q.15.15.213.325t.062.375t-.062.375t-.213.325l-3.6 3.6q-.275.275-.687.275T16.3 12.3q-.3-.3-.3-.712t.3-.713z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3>File Conversions</h3>
|
||||
</div>
|
||||
<ul class="feature-list">
|
||||
<li>PDF to/from images</li>
|
||||
<li>Office documents</li>
|
||||
<li>HTML to PDF</li>
|
||||
<li>Markdown to PDF</li>
|
||||
<li>PDF to Word/Excel</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="feature-card" data-category="automation">
|
||||
<div class="feature-header">
|
||||
<div class="feature-icon-large">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
d="M7.4 17.25q-1.05.875-2.187.8t-1.988-.775t-1.162-1.837t.412-2.338L4.35 10q-.625-.55-.987-1.325T3 7q0-1.65 1.175-2.825T7 3t2.825 1.175T11 7T9.825 9.825T7 11q-.225 0-.45-.025t-.425-.075L4.2 14.15q-.275.45-.175.888t.425.712t.775.313t.875-.313l10.5-9.025q1.05-.875 2.2-.788t2 .788t1.15 1.838t-.425 2.337L19.65 14q.625.55.988 1.325T21 17q0 1.65-1.175 2.825T17 21t-2.825-1.175T13 17t1.175-2.825T17 13q.225 0 .438.025t.412.075l1.95-3.25q.275-.45.175-.888t-.425-.712t-.775-.312t-.875.312zM7 9q.825 0 1.413-.587T9 7t-.587-1.412T7 5t-1.412.588T5 7t.588 1.413T7 9m10 10q.825 0 1.413-.587T19 17t-.587-1.412T17 15t-1.412.588T15 17t.588 1.413T17 19m0-2"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3>Automation</h3>
|
||||
</div>
|
||||
<ul class="feature-list">
|
||||
<li>Multi-step workflows</li>
|
||||
<li>Chain PDF operations</li>
|
||||
<li>Save recurring tasks</li>
|
||||
<li>Batch file processing</li>
|
||||
<li>API integration</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="additional-features">
|
||||
<div class="additional-features-header">
|
||||
<div class="additional-features-icon">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
d="M6 20q-.825 0-1.4125-.5875T4 18t.5875-1.4125T6 16t1.4125.5875T8 18t-.5875 1.4125T6 20m6 0q-.825 0-1.4125-.5875T10 18t.5875-1.4125T12 16t1.4125.5875T14 18t-.5875 1.4125T12 20m6 0q-.825 0-1.4125-.5875T16 18t.5875-1.4125T18 16t1.4125.5875T20 18t-.5875 1.4125T18 20M6 14q-.825 0-1.4125-.5875T4 12t.5875-1.4125T6 10t1.4125.5875T8 12t-.5875 1.4125T6 14m6 0q-.825 0-1.4125-.5875T10 12t.5875-1.4125T12 10t1.4125.5875T14 12t-.5875 1.4125T12 14m6 0q-.825 0-1.4125-.5875T16 12t.5875-1.4125T18 10t1.4125.5875T20 12t-.5875 1.4125T18 14M6 8q-.825 0-1.4125-.5875T4 6t.5875-1.4125T6 4t1.4125.5875T8 6t-.5875 1.4125T6 8m6 0q-.825 0-1.4125-.5875T10 6t.5875-1.4125T12 4t1.4125.5875T14 6t-.5875 1.4125T12 8m6 0q-.825 0-1.4125-.5875T16 6t.5875-1.4125T18 4t1.4125.5875T20 6t-.5875 1.4125T18 8"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3>Plus Many More</h3>
|
||||
</div>
|
||||
<div class="additional-features-grid">
|
||||
<ul>
|
||||
<li>OCR text recognition</li>
|
||||
<li>Compress PDFs</li>
|
||||
<li>Add images & stamps</li>
|
||||
<li>Detect blank pages</li>
|
||||
<li>Extract images</li>
|
||||
<li>Edit metadata</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>Flatten forms</li>
|
||||
<li>PDF/A conversion</li>
|
||||
<li>Add page numbers</li>
|
||||
<li>Remove pages</li>
|
||||
<li>Repair PDFs</li>
|
||||
<li>And 40+ more tools</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user