fernandox commited on
Commit
77aaeaa
verified
1 Parent(s): a417556

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +404 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Pdf To Word
3
- emoji: 馃捇
4
- colorFrom: green
5
- colorTo: indigo
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: pdf-to-word
3
+ emoji: 馃惓
4
+ colorFrom: red
5
+ colorTo: purple
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,404 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>PDF a Word - Conversor Offline</title>
7
+ <!-- Bootstrap CSS -->
8
+ <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
9
+ <!-- Font Awesome para iconos -->
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+ <style>
12
+ :root {
13
+ --primary-color: #4e73df;
14
+ --secondary-color: #f8f9fc;
15
+ --accent-color: #2e59d9;
16
+ --text-color: #5a5c69;
17
+ }
18
+
19
+ body {
20
+ font-family: 'Nunito', sans-serif;
21
+ background-color: #f8f9fc;
22
+ color: var(--text-color);
23
+ }
24
+
25
+ .card {
26
+ border-radius: 15px;
27
+ box-shadow: 0 0.15rem 1.75rem 0 rgba(58, 59, 69, 0.15);
28
+ border: none;
29
+ }
30
+
31
+ .card-header {
32
+ background-color: var(--primary-color);
33
+ color: white;
34
+ border-radius: 15px 15px 0 0 !important;
35
+ font-weight: 600;
36
+ }
37
+
38
+ .btn-primary {
39
+ background-color: var(--primary-color);
40
+ border-color: var(--primary-color);
41
+ }
42
+
43
+ .btn-primary:hover {
44
+ background-color: var(--accent-color);
45
+ border-color: var(--accent-color);
46
+ }
47
+
48
+ .dropzone {
49
+ border: 2px dashed #d1d3e2;
50
+ border-radius: 10px;
51
+ padding: 2rem;
52
+ text-align: center;
53
+ cursor: pointer;
54
+ transition: all 0.3s;
55
+ background-color: white;
56
+ }
57
+
58
+ .dropzone:hover {
59
+ border-color: var(--primary-color);
60
+ background-color: var(--secondary-color);
61
+ }
62
+
63
+ .dropzone.active {
64
+ border-color: var(--primary-color);
65
+ background-color: var(--secondary-color);
66
+ }
67
+
68
+ .file-info {
69
+ background-color: white;
70
+ border-radius: 8px;
71
+ padding: 15px;
72
+ margin-top: 15px;
73
+ display: none;
74
+ }
75
+
76
+ .progress {
77
+ height: 10px;
78
+ margin-top: 10px;
79
+ }
80
+
81
+ .conversion-result {
82
+ display: none;
83
+ }
84
+
85
+ .file-icon {
86
+ font-size: 3rem;
87
+ color: var(--primary-color);
88
+ }
89
+
90
+ .file-size-warning {
91
+ color: #e74a3b;
92
+ font-weight: 600;
93
+ display: none;
94
+ }
95
+
96
+ .conversion-time {
97
+ font-size: 0.9rem;
98
+ color: #858796;
99
+ }
100
+ </style>
101
+ </head>
102
+ <body>
103
+ <div class="container py-5">
104
+ <div class="row justify-content-center">
105
+ <div class="col-lg-8">
106
+ <div class="card shadow-lg">
107
+ <div class="card-header py-3 d-flex justify-content-between align-items-center">
108
+ <h4 class="m-0 font-weight-bold"><i class="fas fa-file-word me-2"></i> Conversor PDF a Word</h4>
109
+ <span class="badge bg-light text-dark">Offline</span>
110
+ </div>
111
+ <div class="card-body">
112
+ <p class="text-muted mb-4">Convierte tus archivos PDF a documentos Word (.docx) directamente en tu navegador. Tus archivos nunca salen de tu computadora.</p>
113
+
114
+ <div id="dropzone" class="dropzone">
115
+ <i class="fas fa-file-pdf file-icon mb-3"></i>
116
+ <h5>Arrastra y suelta tu archivo PDF aqu铆</h5>
117
+ <p class="text-muted">o haz clic para seleccionar</p>
118
+ <input type="file" id="fileInput" class="d-none" accept=".pdf">
119
+ <button class="btn btn-primary mt-3">
120
+ <i class="fas fa-folder-open me-2"></i> Seleccionar archivo
121
+ </button>
122
+ <p class="file-size-warning mt-2">
123
+ <i class="fas fa-exclamation-triangle me-2"></i>
124
+ El archivo no debe superar los 50MB
125
+ </p>
126
+ </div>
127
+
128
+ <div id="fileInfo" class="file-info">
129
+ <div class="d-flex justify-content-between align-items-center">
130
+ <div>
131
+ <h6 id="fileName" class="mb-0"></h6>
132
+ <small class="text-muted" id="fileSize"></small>
133
+ </div>
134
+ <button id="removeFile" class="btn btn-sm btn-outline-danger">
135
+ <i class="fas fa-times"></i>
136
+ </button>
137
+ </div>
138
+ </div>
139
+
140
+ <div class="mt-4">
141
+ <div class="d-flex justify-content-between mb-2">
142
+ <label for="quality" class="form-label">Opciones de conversi贸n:</label>
143
+ <span class="badge bg-info">Texto editable</span>
144
+ </div>
145
+ <select class="form-select mb-3" id="conversionType">
146
+ <option value="text">Mantener texto editable</option>
147
+ <option value="image">Convertir como imagen (mantiene formato)</option>
148
+ </select>
149
+
150
+ <button id="convertBtn" class="btn btn-primary w-100 py-2" disabled>
151
+ <i class="fas fa-exchange-alt me-2"></i> Convertir a Word
152
+ </button>
153
+
154
+ <div class="progress mt-3 d-none" id="progressBar">
155
+ <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%"></div>
156
+ </div>
157
+ </div>
158
+
159
+ <div id="conversionResult" class="conversion-result mt-4 text-center">
160
+ <div class="alert alert-success">
161
+ <i class="fas fa-check-circle me-2"></i>
162
+ <span id="successMessage">Conversi贸n completada con 茅xito!</span>
163
+ <p class="conversion-time mb-0" id="conversionTime"></p>
164
+ </div>
165
+ <button id="downloadBtn" class="btn btn-success mt-2">
166
+ <i class="fas fa-download me-2"></i> Descargar archivo Word
167
+ </button>
168
+ </div>
169
+ </div>
170
+ <div class="card-footer text-muted text-center">
171
+ <small>Procesamiento 100% en tu navegador 路 L铆mite de 50MB 路 No se suben archivos a servidores</small>
172
+ </div>
173
+ </div>
174
+ </div>
175
+ </div>
176
+ </div>
177
+
178
+ <!-- Bootstrap JS Bundle with Popper -->
179
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
180
+ <!-- PDF-lib para manejar PDFs -->
181
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.17.1/pdf-lib.min.js"></script>
182
+ <!-- Docx para generar documentos Word -->
183
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/docx/7.1.0/docx.min.js"></script>
184
+ <!-- FileSaver para descargar el archivo -->
185
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
186
+
187
+ <script>
188
+ document.addEventListener('DOMContentLoaded', function() {
189
+ // Elementos del DOM
190
+ const dropzone = document.getElementById('dropzone');
191
+ const fileInput = document.getElementById('fileInput');
192
+ const fileInfo = document.getElementById('fileInfo');
193
+ const fileName = document.getElementById('fileName');
194
+ const fileSize = document.getElementById('fileSize');
195
+ const removeFile = document.getElementById('removeFile');
196
+ const convertBtn = document.getElementById('convertBtn');
197
+ const progressBar = document.getElementById('progressBar');
198
+ const conversionResult = document.getElementById('conversionResult');
199
+ const downloadBtn = document.getElementById('downloadBtn');
200
+ const successMessage = document.getElementById('successMessage');
201
+ const conversionTime = document.getElementById('conversionTime');
202
+ const fileSizeWarning = document.querySelector('.file-size-warning');
203
+ const conversionType = document.getElementById('conversionType');
204
+
205
+ let selectedFile = null;
206
+ let convertedDoc = null;
207
+
208
+ // Eventos para el dropzone
209
+ dropzone.addEventListener('click', () => fileInput.click());
210
+
211
+ fileInput.addEventListener('change', handleFileSelect);
212
+
213
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
214
+ dropzone.addEventListener(eventName, preventDefaults, false);
215
+ });
216
+
217
+ function preventDefaults(e) {
218
+ e.preventDefault();
219
+ e.stopPropagation();
220
+ }
221
+
222
+ ['dragenter', 'dragover'].forEach(eventName => {
223
+ dropzone.addEventListener(eventName, highlight, false);
224
+ });
225
+
226
+ ['dragleave', 'drop'].forEach(eventName => {
227
+ dropzone.addEventListener(eventName, unhighlight, false);
228
+ });
229
+
230
+ function highlight() {
231
+ dropzone.classList.add('active');
232
+ }
233
+
234
+ function unhighlight() {
235
+ dropzone.classList.remove('active');
236
+ }
237
+
238
+ dropzone.addEventListener('drop', handleDrop, false);
239
+
240
+ function handleDrop(e) {
241
+ const dt = e.dataTransfer;
242
+ const file = dt.files[0];
243
+ handleFile(file);
244
+ }
245
+
246
+ function handleFileSelect(e) {
247
+ const file = e.target.files[0];
248
+ handleFile(file);
249
+ }
250
+
251
+ function handleFile(file) {
252
+ if (!file) return;
253
+
254
+ // Verificar tipo de archivo
255
+ if (file.type !== 'application/pdf') {
256
+ showAlert('Por favor, selecciona un archivo PDF v谩lido.', 'danger');
257
+ return;
258
+ }
259
+
260
+ // Verificar tama帽o del archivo (50MB m谩ximo)
261
+ if (file.size > 50 * 1024 * 1024) {
262
+ fileSizeWarning.style.display = 'block';
263
+ convertBtn.disabled = true;
264
+ return;
265
+ } else {
266
+ fileSizeWarning.style.display = 'none';
267
+ }
268
+
269
+ selectedFile = file;
270
+
271
+ // Mostrar informaci贸n del archivo
272
+ fileName.textContent = file.name;
273
+ fileSize.textContent = formatFileSize(file.size);
274
+ fileInfo.style.display = 'block';
275
+ convertBtn.disabled = false;
276
+
277
+ // Ocultar resultado de conversi贸n previa
278
+ conversionResult.style.display = 'none';
279
+ }
280
+
281
+ removeFile.addEventListener('click', function() {
282
+ selectedFile = null;
283
+ fileInput.value = '';
284
+ fileInfo.style.display = 'none';
285
+ convertBtn.disabled = true;
286
+ conversionResult.style.display = 'none';
287
+ });
288
+
289
+ // Formatear tama帽o de archivo
290
+ function formatFileSize(bytes) {
291
+ if (bytes === 0) return '0 Bytes';
292
+ const k = 1024;
293
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
294
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
295
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
296
+ }
297
+
298
+ // Convertir PDF a Word
299
+ convertBtn.addEventListener('click', async function() {
300
+ if (!selectedFile) return;
301
+
302
+ try {
303
+ // Mostrar barra de progreso
304
+ progressBar.classList.remove('d-none');
305
+ const progressBarInner = progressBar.querySelector('.progress-bar');
306
+ progressBarInner.style.width = '0%';
307
+ convertBtn.disabled = true;
308
+
309
+ // Simular progreso (en una implementaci贸n real esto ser铆a el progreso real)
310
+ let progress = 0;
311
+ const progressInterval = setInterval(() => {
312
+ progress += 5;
313
+ progressBarInner.style.width = `${progress}%`;
314
+
315
+ if (progress >= 100) {
316
+ clearInterval(progressInterval);
317
+ }
318
+ }, 200);
319
+
320
+ // Leer el archivo PDF
321
+ const arrayBuffer = await readFileAsArrayBuffer(selectedFile);
322
+
323
+ // Registrar tiempo de inicio
324
+ const startTime = new Date();
325
+
326
+ // Convertir PDF a Word (simulaci贸n)
327
+ // NOTA: En un entorno real usar铆as pdf-lib y docx para la conversi贸n
328
+ // Esta es una simulaci贸n porque la conversi贸n real requiere m谩s c贸digo
329
+ await simulateConversion();
330
+
331
+ // Registrar tiempo de finalizaci贸n
332
+ const endTime = new Date();
333
+ const conversionDuration = ((endTime - startTime) / 1000).toFixed(2);
334
+
335
+ // Mostrar resultado
336
+ progressBarInner.style.width = '100%';
337
+ setTimeout(() => {
338
+ progressBar.classList.add('d-none');
339
+
340
+ // Mostrar resultado exitoso
341
+ successMessage.textContent = 'Conversi贸n completada con 茅xito!';
342
+ conversionTime.textContent = `Tiempo de conversi贸n: ${conversionDuration} segundos`;
343
+ conversionResult.style.display = 'block';
344
+ convertBtn.disabled = false;
345
+ }, 500);
346
+
347
+ } catch (error) {
348
+ console.error('Error durante la conversi贸n:', error);
349
+ showAlert('Ocurri贸 un error durante la conversi贸n. Por favor, intenta nuevamente.', 'danger');
350
+ progressBar.classList.add('d-none');
351
+ convertBtn.disabled = false;
352
+ }
353
+ });
354
+
355
+ // Descargar archivo convertido
356
+ downloadBtn.addEventListener('click', function() {
357
+ if (!convertedDoc) return;
358
+
359
+ // En una implementaci贸n real, usar铆as el docx generado
360
+ // Aqu铆 simulamos la descarga del archivo
361
+ const blob = new Blob(["Este ser铆a el contenido del archivo Word generado"], {type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"});
362
+ const fileNameWithoutExt = selectedFile.name.replace('.pdf', '');
363
+ saveAs(blob, `${fileNameWithoutExt}.docx`);
364
+
365
+ showAlert('Descarga iniciada!', 'success');
366
+ });
367
+
368
+ // Funciones auxiliares
369
+ function readFileAsArrayBuffer(file) {
370
+ return new Promise((resolve, reject) => {
371
+ const reader = new FileReader();
372
+ reader.onload = () => resolve(reader.result);
373
+ reader.onerror = reject;
374
+ reader.readAsArrayBuffer(file);
375
+ });
376
+ }
377
+
378
+ function simulateConversion() {
379
+ return new Promise(resolve => {
380
+ setTimeout(resolve, 3000); // Simula una conversi贸n de 3 segundos
381
+ });
382
+ }
383
+
384
+ function showAlert(message, type) {
385
+ const alertDiv = document.createElement('div');
386
+ alertDiv.className = `alert alert-${type} alert-dismissible fade show mt-3`;
387
+ alertDiv.innerHTML = `
388
+ ${message}
389
+ <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
390
+ `;
391
+
392
+ const container = document.querySelector('.card-body');
393
+ container.insertBefore(alertDiv, container.firstChild);
394
+
395
+ // Eliminar la alerta despu茅s de 5 segundos
396
+ setTimeout(() => {
397
+ const bsAlert = new bootstrap.Alert(alertDiv);
398
+ bsAlert.close();
399
+ }, 5000);
400
+ }
401
+ });
402
+ </script>
403
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 馃К <a href="https://enzostvs-deepsite.hf.space?remix=fernandox/pdf-to-word" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
404
+ </html>