pdfindex.html27 matches
4<meta charset="UTF-8">
5<meta name="viewport" content="width=device-width, initial-scale=1.0">
6<title>Image to PDF Converter</title>
7<script src="https://cdn.twind.style" crossorigin></script>
8<script src="https://esm.town/v/std/catch"></script>
175<div class="text-center mb-8">
176<h1 class="text-4xl font-bold text-gradient mb-3 glow floating">
177📄 Image to PDF Converter
178</h1>
179<p class="text-gray-300 text-lg font-light">
180Transform your images into professional PDF documents
181</p>
182</div>
188<div class="text-6xl floating glow">🖼️</div>
189<div>
190<label for="imageInput" class="cursor-pointer">
191<span class="btn-3d bg-gradient-to-r from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 text-white px-8 py-4 rounded-xl font-semibold text-lg inline-block">
192✨ Choose Images
193</span>
194<input type="file" id="imageInput" multiple accept="image/*" class="hidden">
195</label>
196</div>
197<p class="text-gray-300 font-medium">
198Select one or more images • JPEG, PNG, GIF, WebP
199</p>
200<p class="text-gray-400 text-sm">
207<div id="fileList" class="hidden">
208<h3 class="text-xl font-semibold text-white mb-4 flex items-center">
209<span class="mr-2">📋</span> Selected Images:
210</h3>
211<div id="fileItems" class="space-y-3"></div>
231232<script>
233const imageInput = document.getElementById('imageInput');
234const fileList = document.getElementById('fileList');
235const fileItems = document.getElementById('fileItems');
241let selectedFiles = [];
242243imageInput.addEventListener('change', function(e) {
244selectedFiles = Array.from(e.target.files);
245
249
250for (const file of selectedFiles) {
251if (!file.type.startsWith('image/')) {
252alert(`Invalid file type: ${file.name}`);
253continue;
302try {
303convertBtn.disabled = true;
304status.textContent = 'Processing images...';
305status.classList.remove('hidden');
306progressBar.classList.remove('hidden');
310const formData = new FormData();
311selectedFiles.forEach(file => {
312formData.append('images', file);
313});
314327}
328329if (!result.images || result.images.length === 0) {
330throw new Error('No images returned from server');
331}
332340let isFirstPage = true;
341342for (let i = 0; i < result.images.length; i++) {
343const imageData = result.images[i];
344
345if (!isFirstPage) {
348isFirstPage = false;
349350// Create image element to get dimensions
351const img = new Image();
352await new Promise((resolve, reject) => {
353img.onload = resolve;
354img.onerror = reject;
355img.src = `data:${imageData.type};base64,${imageData.data}`;
356});
357374imgHeight *= ratio;
375376// Center the image
377const x = (pageWidth - imgWidth) / 2;
378const y = (pageHeight - imgHeight) / 2;
379380pdf.addImage(img.src, 'JPEG', x, y, imgWidth, imgHeight);
381
382progress.style.width = `${60 + (i + 1) / result.images.length * 30}%`;
383}
384389// Download the PDF
390const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-');
391pdf.save(`images-to-pdf-${timestamp}.pdf`);
392393// Reset UI
442const files = dt.files;
443
444// Filter and validate image files
445const validFiles = [];
446const maxFileSize = 10 * 1024 * 1024; // 10MB
447
448for (const file of Array.from(files)) {
449if (!file.type.startsWith('image/')) {
450continue; // Skip non-image files silently
451}
452if (file.size > maxFileSize) {
15});
1617// Handle image to PDF conversion
18app.post("/convert", async (c) => {
19try {
20const body = await c.req.formData();
21const files = body.getAll("images") as File[];
22
23if (!files || files.length === 0) {
24return c.json({ error: "No images provided" }, 400);
25}
2627// Validate file types and sizes
28const validTypes = ["image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp"];
29const maxFileSize = 10 * 1024 * 1024; // 10MB per file
30
3940// Convert files to base64 for client-side processing
41const imageData = [];
42for (const file of files) {
43try {
57const base64 = btoa(binaryString);
58
59imageData.push({
60data: base64,
61type: file.type,
69}
7071return c.json({ images: imageData });
72} catch (error) {
73console.error("Conversion error:", error);
74return c.json({
75error: "Failed to process images",
76details: error.message
77}, 500);
loopyLettersAppGameApp.tsx1 match
363</clipPath>
364</defs>
365<image
366href={imgUrl}
367x={CENTER.x - innerRadius}
twitterNewTweetAlertmain.tsx4 matches
26created_at: string;
27profile_banner_url: string;
28profile_image_url_https: string;
29can_dm: boolean;
30}
137name: `${user.name} (@${user.screen_name})`,
138url: `https://x.com/${user.screen_name}`,
139icon_url: user.profile_image_url_https,
140},
141fields: [
150};
151152// Add image if present
153const mediaEntities = tweet.entities.media;
154if (mediaEntities && mediaEntities.length > 0) {
155embed.image = {
156url: mediaEntities[0].media_url_https,
157};
projectindex.html1 match
8<script src="https://esm.town/v/std/catch"></script>
9<link rel="stylesheet" href="/frontend/style.css">
10<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🍅</text></svg>">
11</head>
12<body class="bg-gray-50 min-h-screen">
we-the-undersignedindex.hbs2 matches
12<link
13rel="icon"
14type="image/x-icon"
15sizes="any"
16href="https://cdn.glitch.global/de7a389a-399d-4d75-a57e-15b49d8cbe43/favicon.ico?v=1744749668124"
30<meta property="og:url" content="{{seo.url}}" />
31<meta property="og:description" content="{{seo.description}}" />
32<meta property="og:image" content="{{seo.image}}" />
33<meta name="twitter:card" content="summary" />
34
we-the-undersignedadmin.hbs1 match
1112<meta charset="utf-8" />
13<link rel="icon" type="image/x-icon" sizes="any" href="https://cdn.glitch.global/de7a389a-399d-4d75-a57e-15b49d8cbe43/favicon.ico?v=1744749668124">
14<meta name="viewport" content="width=device-width, initial-scale=1" />
15
we-the-undersignedseo.json1 match
4"description": "An open letter",
5"url": "glitch-default",
6"image": "https://cdn.glitch.com/605e2a51-d45f-4d87-a285-9410ad350515%2Fhello-node-social.png?v=1618161394375",
7"db": "SQLite"
8}
we-the-undersignedstyle.css2 matches
14--color-accent: #8a3434;
15--wrapper-height: 87vh;
16--image-max-width: 300px;
17--image-margin: 3rem;
18--font-family: Tiempos, Iowan Old Style, Georgia, Times New Roman, serif;
19--font-family-header:
auto-commitgenerate.tsx2 matches
60}
6162function validateImage(url) {
63return validateURL(url);
64}
183
184<h1>
185<img width=50 src="${validateImage(pfp)}">
186${escapeHTML(title)}
187</h1>