Spaces:
Running
Running
undefined - Initial Deployment
Browse files- README.md +7 -5
- index.html +753 -19
README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 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: text-to-document-area
|
| 3 |
+
emoji: 🐳
|
| 4 |
+
colorFrom: red
|
| 5 |
+
colorTo: yellow
|
| 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,753 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Integrated App Suite</title>
|
| 7 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 8 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 9 |
+
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
| 10 |
+
<!-- Shared library for PDF generation -->
|
| 11 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js" integrity="sha512-GsLlZN/3F2ErC5ifS5QtgpiJtWd43JWSuIgh7mbzZ8zBps+dvLusV+eNQATqgA/HdeKFVgA5v3S/cIrLF7QnIg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
| 12 |
+
<style>
|
| 13 |
+
/* --- GLOBAL & LAYOUT STYLES --- */
|
| 14 |
+
:root {
|
| 15 |
+
--primary-color: #00e5ff;
|
| 16 |
+
--danger-color: #ff4757;
|
| 17 |
+
--secondary-color: #1d2b3a;
|
| 18 |
+
--dark-bg: #1a1d20;
|
| 19 |
+
--light-text: #f0f0f0;
|
| 20 |
+
--menu-bg: rgba(29, 43, 58, 0.6);
|
| 21 |
+
--container-bg: rgba(255, 255, 255, 0.08);
|
| 22 |
+
}
|
| 23 |
+
* {
|
| 24 |
+
margin: 0;
|
| 25 |
+
padding: 0;
|
| 26 |
+
box-sizing: border-box;
|
| 27 |
+
}
|
| 28 |
+
body {
|
| 29 |
+
font-family: 'Poppins', sans-serif;
|
| 30 |
+
background-color: var(--dark-bg);
|
| 31 |
+
color: var(--light-text);
|
| 32 |
+
display: flex;
|
| 33 |
+
height: 100vh;
|
| 34 |
+
overflow: hidden;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
/* --- SIDE MENU STYLES --- */
|
| 38 |
+
#side-menu {
|
| 39 |
+
width: 240px;
|
| 40 |
+
height: 100vh;
|
| 41 |
+
background: var(--menu-bg);
|
| 42 |
+
backdrop-filter: blur(20px);
|
| 43 |
+
-webkit-backdrop-filter: blur(20px);
|
| 44 |
+
border-right: 1px solid rgba(255, 255, 255, 0.1);
|
| 45 |
+
padding: 25px 15px;
|
| 46 |
+
display: flex;
|
| 47 |
+
flex-direction: column;
|
| 48 |
+
transition: width 0.3s ease;
|
| 49 |
+
}
|
| 50 |
+
.menu-header {
|
| 51 |
+
display: flex;
|
| 52 |
+
align-items: center;
|
| 53 |
+
gap: 12px;
|
| 54 |
+
padding: 0 10px 25px 10px;
|
| 55 |
+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
| 56 |
+
margin-bottom: 25px;
|
| 57 |
+
}
|
| 58 |
+
.menu-header .logo {
|
| 59 |
+
width: 40px;
|
| 60 |
+
height: 40px;
|
| 61 |
+
background: var(--primary-color);
|
| 62 |
+
border-radius: 50%;
|
| 63 |
+
display: grid;
|
| 64 |
+
place-items: center;
|
| 65 |
+
font-weight: 700;
|
| 66 |
+
color: #111;
|
| 67 |
+
font-size: 1.5rem;
|
| 68 |
+
}
|
| 69 |
+
.menu-header h2 {
|
| 70 |
+
font-size: 1.3rem;
|
| 71 |
+
font-weight: 600;
|
| 72 |
+
}
|
| 73 |
+
.menu-nav {
|
| 74 |
+
list-style: none;
|
| 75 |
+
}
|
| 76 |
+
.menu-btn {
|
| 77 |
+
display: flex;
|
| 78 |
+
align-items: center;
|
| 79 |
+
gap: 15px;
|
| 80 |
+
width: 100%;
|
| 81 |
+
padding: 15px;
|
| 82 |
+
margin-bottom: 8px;
|
| 83 |
+
border-radius: 8px;
|
| 84 |
+
border: none;
|
| 85 |
+
background: transparent;
|
| 86 |
+
color: var(--light-text);
|
| 87 |
+
cursor: pointer;
|
| 88 |
+
font-size: 1rem;
|
| 89 |
+
font-family: 'Poppins', sans-serif;
|
| 90 |
+
text-align: left;
|
| 91 |
+
transition: background-color 0.2s ease, color 0.2s ease;
|
| 92 |
+
}
|
| 93 |
+
.menu-btn svg {
|
| 94 |
+
width: 22px;
|
| 95 |
+
height: 22px;
|
| 96 |
+
fill: currentColor;
|
| 97 |
+
opacity: 0.7;
|
| 98 |
+
transition: opacity 0.2s ease;
|
| 99 |
+
}
|
| 100 |
+
.menu-btn:hover {
|
| 101 |
+
background-color: rgba(255, 255, 255, 0.1);
|
| 102 |
+
}
|
| 103 |
+
.menu-btn.active {
|
| 104 |
+
background-color: var(--primary-color);
|
| 105 |
+
color: #111;
|
| 106 |
+
font-weight: 600;
|
| 107 |
+
}
|
| 108 |
+
.menu-btn.active svg {
|
| 109 |
+
opacity: 1;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
/* --- MAIN CONTENT AREA --- */
|
| 113 |
+
#main-content {
|
| 114 |
+
flex-grow: 1;
|
| 115 |
+
height: 100vh;
|
| 116 |
+
overflow-y: auto;
|
| 117 |
+
background-image: linear-gradient(135deg, rgba(35, 37, 38, 0.95) 0%, rgba(65, 67, 69, 0.85) 100%),
|
| 118 |
+
url('https://images.pexels.com/photos/325185/pexels-photo-325185.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2');
|
| 119 |
+
background-size: cover;
|
| 120 |
+
background-position: center;
|
| 121 |
+
}
|
| 122 |
+
.app-view {
|
| 123 |
+
display: none; /* Hidden by default */
|
| 124 |
+
justify-content: center;
|
| 125 |
+
align-items: flex-start;
|
| 126 |
+
padding: 40px 20px;
|
| 127 |
+
min-height: 100%;
|
| 128 |
+
}
|
| 129 |
+
.app-view.active-view {
|
| 130 |
+
display: flex;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
/* --- WELCOME PAGE STYLES --- */
|
| 134 |
+
#welcome-view .welcome-container {
|
| 135 |
+
display: flex;
|
| 136 |
+
flex-direction: column;
|
| 137 |
+
justify-content: center;
|
| 138 |
+
align-items: center;
|
| 139 |
+
text-align: center;
|
| 140 |
+
height: 100%;
|
| 141 |
+
color: white;
|
| 142 |
+
}
|
| 143 |
+
#welcome-view h1 {
|
| 144 |
+
font-size: 4rem;
|
| 145 |
+
font-weight: 700;
|
| 146 |
+
text-shadow: 0 4px 15px rgba(0,0,0,0.4);
|
| 147 |
+
}
|
| 148 |
+
#welcome-view .tagline {
|
| 149 |
+
font-size: 1.5rem;
|
| 150 |
+
font-weight: 400;
|
| 151 |
+
color: rgba(255,255,255,0.8);
|
| 152 |
+
margin-top: 10px;
|
| 153 |
+
max-width: 600px;
|
| 154 |
+
}
|
| 155 |
+
#welcome-view .highlight {
|
| 156 |
+
color: var(--primary-color);
|
| 157 |
+
font-weight: 600;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
/* --- SHARED APP COMPONENT STYLES --- */
|
| 161 |
+
.app-container {
|
| 162 |
+
max-width: 900px;
|
| 163 |
+
width: 100%;
|
| 164 |
+
background: var(--container-bg);
|
| 165 |
+
backdrop-filter: blur(15px);
|
| 166 |
+
-webkit-backdrop-filter: blur(15px);
|
| 167 |
+
border-radius: 20px;
|
| 168 |
+
border: 1px solid rgba(255, 255, 255, 0.18);
|
| 169 |
+
padding: 30px;
|
| 170 |
+
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
|
| 171 |
+
}
|
| 172 |
+
.header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; }
|
| 173 |
+
.header h1 { margin: 0; font-weight: 700; font-size: 2.2rem; text-shadow: 0 2px 4px rgba(0,0,0,0.2); }
|
| 174 |
+
.icon-btn { background: none; border: none; cursor: pointer; padding: 5px; color: rgba(255,255,255,0.7); transition: color 0.3s ease; }
|
| 175 |
+
.icon-btn:hover { color: white; }
|
| 176 |
+
.icon-btn svg { width: 24px; height: 24px; fill: currentColor; }
|
| 177 |
+
.instructions {
|
| 178 |
+
background: rgba(0,0,0,0.2); border-radius: 8px; margin-bottom: 25px;
|
| 179 |
+
max-height: 0; overflow: hidden; transition: max-height 0.5s ease-out, padding 0.5s ease-out; padding: 0 20px;
|
| 180 |
+
}
|
| 181 |
+
.instructions.visible { max-height: 300px; padding: 15px 20px; }
|
| 182 |
+
.instructions ul { list-style-type: '✓ '; padding-left: 20px; }
|
| 183 |
+
.instructions li { margin-bottom: 8px; }
|
| 184 |
+
button { padding: 12px 20px; border: none; border-radius: 8px; font-weight: 600; font-size: 0.9rem; cursor: pointer; user-select: none; transition: transform 0.2s ease, background-color 0.2s ease, opacity 0.2s ease; }
|
| 185 |
+
button:hover:not(:disabled) { transform: translateY(-3px); }
|
| 186 |
+
button:disabled { cursor: not-allowed; opacity: 0.6; }
|
| 187 |
+
.btn-secondary { background-color: transparent; color: var(--primary-color); border: 2px solid var(--primary-color); flex-grow: 1; }
|
| 188 |
+
.btn-secondary:hover:not(:disabled) { background-color: rgba(0, 229, 255, 0.1); }
|
| 189 |
+
.results {
|
| 190 |
+
background: rgba(0, 0, 0, 0.25); padding: 10px 25px; border-radius: 12px;
|
| 191 |
+
margin-bottom: 25px; min-height: 100px; max-height: 500px; overflow-y: auto;
|
| 192 |
+
line-height: 1.6; transition: all 0.3s ease;
|
| 193 |
+
}
|
| 194 |
+
.results[contenteditable="true"] {
|
| 195 |
+
outline: 2px solid var(--primary-color);
|
| 196 |
+
box-shadow: 0 0 15px rgba(0, 229, 255, 0.3);
|
| 197 |
+
}
|
| 198 |
+
.export-buttons { display: flex; gap: 10px; justify-content: space-between; flex-wrap: wrap; }
|
| 199 |
+
|
| 200 |
+
/* --- CV FORGE SPECIFIC STYLES --- */
|
| 201 |
+
#cv_cvForm { display: flex; flex-direction: column; gap: 25px; margin-bottom: 30px; }
|
| 202 |
+
fieldset { border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 12px; padding: 20px; background: rgba(0,0,0,0.15); }
|
| 203 |
+
legend { padding: 0 10px; font-weight: 600; font-size: 1.2rem; color: var(--primary-color); }
|
| 204 |
+
.form-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 15px; }
|
| 205 |
+
.form-group { display: flex; flex-direction: column; }
|
| 206 |
+
.form-group.full-width { grid-column: 1 / -1; }
|
| 207 |
+
label { margin-bottom: 8px; font-weight: 400; font-size: 0.9rem; color: rgba(255,255,255,0.8); }
|
| 208 |
+
input[type="text"], input[type="date"], input[type="tel"], input[type="email"], textarea {
|
| 209 |
+
background: rgba(0,0,0,0.3); border: 1px solid rgba(255,255,255,0.3); border-radius: 6px; padding: 10px;
|
| 210 |
+
color: white; font-family: 'Poppins', sans-serif; font-size: 1rem; transition: border-color 0.3s, box-shadow 0.3s;
|
| 211 |
+
}
|
| 212 |
+
input:focus, textarea:focus { outline: none; border-color: var(--primary-color); box-shadow: 0 0 8px rgba(0, 229, 255, 0.5); }
|
| 213 |
+
textarea { resize: vertical; min-height: 100px; }
|
| 214 |
+
.dynamic-section-item { background: rgba(0,0,0,0.2); padding: 15px; border-radius: 8px; margin-bottom: 15px; border-left: 3px solid var(--primary-color); position: relative; }
|
| 215 |
+
.remove-btn { position: absolute; top: 10px; right: 10px; background-color: var(--danger-color); color: white; border: none; border-radius: 50%; width: 24px; height: 24px; font-weight: bold; cursor: pointer; line-height: 24px; text-align: center; z-index: 2; }
|
| 216 |
+
.add-btn { background-color: var(--primary-color); color: #111; font-weight: 600; }
|
| 217 |
+
.add-btn:hover { background-color: #33eaff; }
|
| 218 |
+
#cv_generateBtn { background-color: var(--danger-color); color: white; width: 100%; margin-bottom: 25px; font-size: 1.1rem; }
|
| 219 |
+
#cv_generateBtn:hover:not(:disabled) { background-color: #ff6b81; }
|
| 220 |
+
#cv_results[contenteditable="true"] { background: rgba(255, 255, 255, 0.95); color: #333; }
|
| 221 |
+
.cv-container { padding: 20px; }
|
| 222 |
+
.cv-header { text-align: center; margin-bottom: 25px; }
|
| 223 |
+
.cv-name { font-size: 2.5em; color: var(--primary-color); margin: 0; }
|
| 224 |
+
.cv-contact { font-size: 1em; color: #ccc; }
|
| 225 |
+
.cv-contact a { color: var(--primary-color); text-decoration: none; }
|
| 226 |
+
.cv-section { margin-bottom: 20px; }
|
| 227 |
+
.cv-section-title { font-size: 1.5em; color: var(--primary-color); border-bottom: 2px solid var(--primary-color); padding-bottom: 5px; margin-bottom: 15px; }
|
| 228 |
+
.cv-item { margin-bottom: 15px; }
|
| 229 |
+
.cv-item-title { font-size: 1.1em; font-weight: bold; }
|
| 230 |
+
.cv-item-subtitle { font-size: 1em; font-style: italic; color: #bbb; }
|
| 231 |
+
.cv-item-dates { float: right; font-style: italic; color: #bbb; }
|
| 232 |
+
.cv-item-description { margin-top: 5px; padding-left: 20px; }
|
| 233 |
+
.cv-skills-list { list-style: none; padding: 0; column-count: 2; }
|
| 234 |
+
#cv_results[contenteditable="true"] .cv-section-title, #cv_results[contenteditable="true"] .cv-name { color: #0077b5; }
|
| 235 |
+
#cv_results[contenteditable="true"] .cv-contact, #cv_results[contenteditable="true"] .cv-item-subtitle, #cv_results[contenteditable="true"] .cv-item-dates { color: #555; }
|
| 236 |
+
|
| 237 |
+
/* --- TEXTIFY PRO SPECIFIC STYLES --- */
|
| 238 |
+
#textify_uploadArea {
|
| 239 |
+
border: 2px dashed rgba(255, 255, 255, 0.4); padding: 40px 20px; text-align: center; margin-bottom: 30px;
|
| 240 |
+
background: rgba(0,0,0,0.2); border-radius: 12px; cursor: pointer; transition: background-color 0.3s ease, border-color 0.3s ease; user-select: none;
|
| 241 |
+
}
|
| 242 |
+
#textify_uploadArea:hover, #textify_uploadArea.dragover { background-color: rgba(0, 229, 255, 0.1); border-color: var(--primary-color); }
|
| 243 |
+
#textify_fileInput { display: none; }
|
| 244 |
+
#textify_settingsMenu {
|
| 245 |
+
position: absolute; top: 80px; right: 30px; width: 280px; background: rgba(40, 40, 40, 0.7); backdrop-filter: blur(10px);
|
| 246 |
+
border-radius: 12px; border: 1px solid rgba(255, 255, 255, 0.2); padding: 20px; z-index: 100; box-shadow: 0 8px 20px rgba(0,0,0,0.4);
|
| 247 |
+
opacity: 0; transform: translateY(-10px); pointer-events: none; transition: opacity 0.3s ease, transform 0.3s ease;
|
| 248 |
+
}
|
| 249 |
+
#textify_settingsMenu.visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
|
| 250 |
+
.setting-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; }
|
| 251 |
+
.setting-header h3 { margin: 0; font-size: 1.1rem; }
|
| 252 |
+
.close-btn { font-size: 1.5rem; color: rgba(255,255,255,0.7); cursor: pointer; line-height: 1; }
|
| 253 |
+
.close-btn:hover { color: white; }
|
| 254 |
+
.control-group { margin-bottom: 20px; }
|
| 255 |
+
.control-group label { display: block; margin-bottom: 10px; font-weight: 600; }
|
| 256 |
+
#textify_marginControl { width: 100%; cursor: pointer; }
|
| 257 |
+
.layout-control label { display: inline-block; background: rgba(0,0,0,0.3); padding: 8px 15px; border-radius: 6px; cursor: pointer; margin-right: 10px; border: 2px solid transparent; transition: background-color 0.2s, border-color 0.2s; }
|
| 258 |
+
.layout-control input[type="radio"] { display: none; }
|
| 259 |
+
.layout-control input[type="radio"]:checked + label { background-color: rgba(0, 229, 255, 0.2); border-color: var(--primary-color); color: white; }
|
| 260 |
+
#textify_preview { display: flex; gap: var(--image-margin, 10px); margin-bottom: 30px; min-height: 130px; background: rgba(0, 0, 0, 0.25); padding: 15px; border-radius: 12px; align-content: flex-start; transition: all 0.3s ease; }
|
| 261 |
+
#textify_preview.layout-row { flex-wrap: wrap; flex-direction: row; }
|
| 262 |
+
#textify_preview.layout-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); }
|
| 263 |
+
#textify_preview:empty::before { content: "Your uploaded images will appear here..."; width: 100%; text-align: center; align-self: center; color: rgba(255, 255, 255, 0.5); font-style: italic; }
|
| 264 |
+
.image-thumb { width: 100px; height: 100px; object-fit: cover; border: 3px solid transparent; border-radius: 8px; cursor: grab; box-shadow: 0 4px 10px rgba(0,0,0,0.3); transition: transform 0.2s ease, box-shadow 0.2s ease; }
|
| 265 |
+
.image-thumb:hover { transform: scale(1.05); }
|
| 266 |
+
.dragging { opacity: 0.4; transform: scale(0.95); cursor: grabbing !important; box-shadow: 0 0 20px var(--primary-color); }
|
| 267 |
+
#textify_convertBtn { background-color: var(--danger-color); color: white; width: 100%; margin-bottom: 25px; font-size: 1rem; }
|
| 268 |
+
#textify_convertBtn:hover:not(:disabled) { background-color: #ff6b81; }
|
| 269 |
+
#textify_results[contenteditable="true"] { background: rgba(0, 0, 0, 0.4); }
|
| 270 |
+
#textify_results h1, #textify_results h2, #textify_results h3 { color: var(--primary-color); margin-top: 1.2em; margin-bottom: 0.5em; }
|
| 271 |
+
#textify_results p { margin-bottom: 1em; }
|
| 272 |
+
#textify_results ul, #textify_results ol { padding-left: 25px; }
|
| 273 |
+
#textify_results hr { border: none; height: 1px; background-color: rgba(255,255,255,0.2); margin: 20px 0; }
|
| 274 |
+
|
| 275 |
+
/* --- RESPONSIVE DESIGN --- */
|
| 276 |
+
@media (max-width: 768px) {
|
| 277 |
+
body {
|
| 278 |
+
flex-direction: column;
|
| 279 |
+
}
|
| 280 |
+
#side-menu {
|
| 281 |
+
width: 100%;
|
| 282 |
+
height: auto;
|
| 283 |
+
flex-direction: row;
|
| 284 |
+
align-items: center;
|
| 285 |
+
padding: 10px;
|
| 286 |
+
border-right: none;
|
| 287 |
+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
| 288 |
+
}
|
| 289 |
+
.menu-header {
|
| 290 |
+
padding: 0;
|
| 291 |
+
margin: 0;
|
| 292 |
+
border: none;
|
| 293 |
+
}
|
| 294 |
+
.menu-header h2 { display: none; }
|
| 295 |
+
.menu-nav {
|
| 296 |
+
display: flex;
|
| 297 |
+
gap: 5px;
|
| 298 |
+
}
|
| 299 |
+
.menu-btn {
|
| 300 |
+
padding: 10px;
|
| 301 |
+
margin: 0;
|
| 302 |
+
gap: 8px;
|
| 303 |
+
}
|
| 304 |
+
.menu-btn span {
|
| 305 |
+
display: none;
|
| 306 |
+
}
|
| 307 |
+
#main-content {
|
| 308 |
+
height: calc(100vh - 65px); /* Adjust based on top bar height */
|
| 309 |
+
}
|
| 310 |
+
.app-view {
|
| 311 |
+
padding: 20px 10px;
|
| 312 |
+
}
|
| 313 |
+
#welcome-view h1 { font-size: 2.5rem; }
|
| 314 |
+
#welcome-view .tagline { font-size: 1.1rem; }
|
| 315 |
+
}
|
| 316 |
+
</style>
|
| 317 |
+
</head>
|
| 318 |
+
<body>
|
| 319 |
+
|
| 320 |
+
<!-- =========== SIDE MENU =========== -->
|
| 321 |
+
<nav id="side-menu">
|
| 322 |
+
<div class="menu-header">
|
| 323 |
+
<div class="logo">S</div>
|
| 324 |
+
<h2>App Suite</h2>
|
| 325 |
+
</div>
|
| 326 |
+
<ul class="menu-nav">
|
| 327 |
+
<li>
|
| 328 |
+
<button class="menu-btn" data-view="welcome-view" onclick="showView('welcome-view', this)">
|
| 329 |
+
<svg viewBox="0 0 24 24"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/></svg>
|
| 330 |
+
<span>Home</span>
|
| 331 |
+
</button>
|
| 332 |
+
</li>
|
| 333 |
+
<li>
|
| 334 |
+
<button class="menu-btn" data-view="cv-forge-view" onclick="showView('cv-forge-view', this)">
|
| 335 |
+
<svg viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zM6 20V4h7v5h5v11H6z"/></svg>
|
| 336 |
+
<span>CV Forge</span>
|
| 337 |
+
</button>
|
| 338 |
+
</li>
|
| 339 |
+
<li>
|
| 340 |
+
<button class="menu-btn" data-view="textify-pro-view" onclick="showView('textify-pro-view', this)">
|
| 341 |
+
<svg viewBox="0 0 24 24"><path d="M20 4v12H8V4h12m0-2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6z M12 11h-2V9h2v2zm-2-4h2V5h-2v2zm4 4h-2V9h2v2zm0-4h2V5h-2v2z"/></svg>
|
| 342 |
+
<span>Textify Pro</span>
|
| 343 |
+
</button>
|
| 344 |
+
</li>
|
| 345 |
+
</ul>
|
| 346 |
+
</nav>
|
| 347 |
+
|
| 348 |
+
<!-- =========== MAIN CONTENT WRAPPER =========== -->
|
| 349 |
+
<main id="main-content">
|
| 350 |
+
|
| 351 |
+
<!-- =========== WELCOME PAGE =========== -->
|
| 352 |
+
<div id="welcome-view" class="app-view">
|
| 353 |
+
<div class="welcome-container">
|
| 354 |
+
<h1>Integrated App Suite</h1>
|
| 355 |
+
<p class="tagline">Craft your professional story with <span class="highlight">CV Forge</span>, or bring images to life with <span class="highlight">Textify Pro</span>. Your productivity hub starts here.</p>
|
| 356 |
+
</div>
|
| 357 |
+
</div>
|
| 358 |
+
|
| 359 |
+
<!-- =========== CV FORGE APP =========== -->
|
| 360 |
+
<div id="cv-forge-view" class="app-view">
|
| 361 |
+
<div class="app-container" id="cv_appContainer">
|
| 362 |
+
<div class="header">
|
| 363 |
+
<h1>CV Forge</h1>
|
| 364 |
+
<div class="header-icons">
|
| 365 |
+
<button class="icon-btn" id="cv_instructionsBtn" title="Show Instructions">
|
| 366 |
+
<svg viewBox="0 0 24 24"><path d="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10,10-4.48,10-10S17.52,2,12,2zm1,15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>
|
| 367 |
+
</button>
|
| 368 |
+
</div>
|
| 369 |
+
</div>
|
| 370 |
+
<div class="instructions" id="cv_instructionsPanel"><h4>How to Use CV Forge:</h4><ul><li><b>Fill in the Details:</b> Complete the form with your personal and professional information.</li><li><b>Add Entries:</b> Use the "Add" buttons for education, experience, and references.</li><li><b>Generate:</b> Press the big red button to create your formatted CV.</li><li><b>Edit & Export:</b> Click the results to fine-tune, then download as PDF, Word, or TXT.</li></ul></div>
|
| 371 |
+
<form id="cv_cvForm">
|
| 372 |
+
<fieldset><legend>Personal Details</legend><div class="form-grid"><div class="form-group"><label for="cv_fullName">Full Name</label><input type="text" id="cv_fullName" placeholder="e.g., Jane Doe"></div><div class="form-group"><label for="cv_dob">Date of Birth</label><input type="date" id="cv_dob"></div><div class="form-group"><label for="cv_phone">Phone Number</label><input type="tel" id="cv_phone" placeholder="e.g., (123) 456-7890"></div><div class="form-group"><label for="cv_email">Email Address</label><input type="email" id="cv_email" placeholder="e.g., jane.doe@example.com"></div><div class="form-group full-width"><label for="cv_address">Address</label><input type="text" id="cv_address" placeholder="e.g., 123 Main St, Anytown, USA"></div><div class="form-group full-width"><label for="cv_about">About / Professional Summary</label><textarea id="cv_about" placeholder="Write a short summary..."></textarea></div></div></fieldset>
|
| 373 |
+
<fieldset><legend>Work Experience</legend><div id="cv_workExperienceSection"></div><button type="button" class="add-btn" onclick="cv_addDynamicEntry('experience')">+ Add Experience</button></fieldset>
|
| 374 |
+
<fieldset><legend>Education Background</legend><div id="cv_educationSection"></div><button type="button" class="add-btn" onclick="cv_addDynamicEntry('education')">+ Add Education</button></fieldset>
|
| 375 |
+
<fieldset><legend>Skills & Accomplishments</legend><div class="form-grid"><div class="form-group full-width"><label for="cv_skills">Skills (comma-separated)</label><input type="text" id="cv_skills" placeholder="e.g., JavaScript, Project Management"></div><div class="form-group full-width"><label for="cv_accomplishments">Key Accomplishments (one per line)</label><textarea id="cv_accomplishments" placeholder="e.g., Increased sales by 20%"></textarea></div></div></fieldset>
|
| 376 |
+
<fieldset><legend>References</legend><div id="cv_referencesSection"></div><button type="button" class="add-btn" onclick="cv_addDynamicEntry('references')">+ Add Reference</button></fieldset>
|
| 377 |
+
</form>
|
| 378 |
+
<button id="cv_generateBtn">Generate CV</button>
|
| 379 |
+
<div class="results" id="cv_results" contenteditable="false"><p style="color: rgba(255,255,255,0.5); text-align: center; margin-top: 20px;">Your generated CV will appear here.</p></div>
|
| 380 |
+
<div class="export-buttons">
|
| 381 |
+
<button class="btn-secondary" id="cv_downloadPdfBtn">Download PDF</button>
|
| 382 |
+
<button class="btn-secondary" id="cv_downloadWordBtn">Download Word</button>
|
| 383 |
+
<button class="btn-secondary" id="cv_downloadTxtBtn">Download TXT</button>
|
| 384 |
+
<button class="btn-secondary" id="cv_printBtn">Print</button>
|
| 385 |
+
</div>
|
| 386 |
+
</div>
|
| 387 |
+
</div>
|
| 388 |
+
|
| 389 |
+
<!-- =========== TEXTIFY PRO APP =========== -->
|
| 390 |
+
<div id="textify-pro-view" class="app-view">
|
| 391 |
+
<div class="app-container" id="textify_appContainer">
|
| 392 |
+
<div class="header">
|
| 393 |
+
<h1>Textify Pro</h1>
|
| 394 |
+
<div class="header-icons">
|
| 395 |
+
<button class="icon-btn" id="textify_instructionsBtn"><svg viewBox="0 0 24 24"><path d="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10,10-4.48,10-10S17.52,2,12,2zm1,15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg></button>
|
| 396 |
+
<button class="icon-btn" id="textify_settingsBtn"><svg viewBox="0 0 24 24"><path d="M19.44,12.99l.01-0.06c0-0.23-0.04-0.46-0.1-0.68l2.09-1.65c0.19-0.15,0.24-0.42,0.11-0.64l-1.99-3.46c-0.13-0.22-0.39-0.31-0.61-0.22l-2.58,1.03C15.8,7.1,15.17,6.83,14.49,6.6l-0.37-2.82C14.07,3.51,13.82,3.33,13.56,3.33h-3.99c-0.26,0-0.51,0.18-0.56,0.45L8.64,6.6C7.96,6.83,7.33,7.1,6.8,7.36L4.22,6.33C4,6.24,3.74,6.33,3.61,6.55L1.62,10.01c-0.13,0.22-0.08,0.49,0.11,0.64l2.09,1.65c-0.06,0.22-0.1,0.45-0.1,0.68l-0.01,0.06c0,0.23,0.04,0.46,0.1,0.68L1.73,14.97c-0.19,0.15-0.24,0.42-0.11,0.64l1.99,3.46c0.13,0.22,0.39,0.31,0.61,0.22l2.58-1.03c0.53,0.26,1.16,0.53,1.84,0.73l0.37,2.82c0.05,0.27,0.3,0.45,0.56,0.45h3.99c0.26,0,0.51-0.18,0.56-0.45l0.37-2.82c0.68-0.2,1.31-0.47,1.84-0.73l2.58,1.03c0.22,0.09,0.48-0.01,0.61-0.22l1.99-3.46c0.13-0.22,0.08-0.49-0.11-0.64l-2.09-1.65C19.4,13.45,19.44,13.22,19.44,12.99z M11.56,15.5c-1.93,0-3.5-1.57-3.5-3.5s1.57-3.5,3.5-3.5s3.5,1.57,3.5,3.5S13.49,15.5,11.56,15.5z"/></svg></button>
|
| 397 |
+
</div>
|
| 398 |
+
</div>
|
| 399 |
+
<div class="instructions" id="textify_instructionsPanel"><h4>How to Use Textify Pro:</h4><ul><li><b>Upload & Re-order:</b> Click or drag images, then reorder them as needed.</li><li><b>Convert:</b> Press the red button to extract text with the AI.</li><li><b>Edit:</b> Click the results area to fix any errors directly.</li><li><b>Export:</b> Use the buttons to download as PDF, Word, TXT, or Print.</li></ul></div>
|
| 400 |
+
<div class="settings-menu" id="textify_settingsMenu"><div class="setting-header"><h3>Settings</h3><span class="close-btn" id="textify_closeSettingsBtn">×</span></div><div class="control-group"><label for="textify_marginControl">Image Spacing:</label><input type="range" id="textify_marginControl" min="2" max="40" value="10" /></div><div class="control-group"><label>Image Layout:</label><div class="layout-control"><input type="radio" id="textify_layoutRow" name="layout" value="row" checked><label for="textify_layoutRow">Row</label><input type="radio" id="textify_layoutGrid" name="layout" value="grid"><label for="textify_layoutGrid">Grid</label></div></div></div>
|
| 401 |
+
<div class="upload-area" id="textify_uploadArea" onclick="textify_fileInput.click()"><input type="file" id="textify_fileInput" multiple accept="image/*" />Click or Drag & Drop Images Here</div>
|
| 402 |
+
<div class="images-preview layout-row" id="textify_preview"></div>
|
| 403 |
+
<button id="textify_convertBtn" onclick="textify_convertImages()">Convert to Text</button>
|
| 404 |
+
<div class="results" id="textify_results" contenteditable="false"><p style="color: rgba(255,255,255,0.5); text-align: center; margin-top: 20px;">Your converted text will appear here.</p></div>
|
| 405 |
+
<div class="export-buttons">
|
| 406 |
+
<button class="btn-secondary" id="textify_downloadPdfBtn">Download PDF</button>
|
| 407 |
+
<button class="btn-secondary" id="textify_downloadWordBtn">Download Word</button>
|
| 408 |
+
<button class="btn-secondary" id="textify_downloadTxtBtn">Download TXT</button>
|
| 409 |
+
<button class="btn-secondary" id="textify_printBtn">Print</button>
|
| 410 |
+
</div>
|
| 411 |
+
</div>
|
| 412 |
+
</div>
|
| 413 |
+
|
| 414 |
+
</main>
|
| 415 |
+
|
| 416 |
+
<script>
|
| 417 |
+
// =========== GLOBAL APP SWITCHING LOGIC ===========
|
| 418 |
+
function showView(viewId, clickedButton) {
|
| 419 |
+
// Hide all views
|
| 420 |
+
document.querySelectorAll('.app-view').forEach(view => {
|
| 421 |
+
view.classList.remove('active-view');
|
| 422 |
+
});
|
| 423 |
+
|
| 424 |
+
// Deactivate all menu buttons
|
| 425 |
+
document.querySelectorAll('.menu-btn').forEach(btn => {
|
| 426 |
+
btn.classList.remove('active');
|
| 427 |
+
});
|
| 428 |
+
|
| 429 |
+
// Show the selected view
|
| 430 |
+
document.getElementById(viewId).classList.add('active-view');
|
| 431 |
+
|
| 432 |
+
// Activate the clicked button
|
| 433 |
+
if(clickedButton) {
|
| 434 |
+
clickedButton.classList.add('active');
|
| 435 |
+
} else {
|
| 436 |
+
// Fallback for initial load
|
| 437 |
+
document.querySelector(`.menu-btn[data-view="${viewId}"]`).classList.add('active');
|
| 438 |
+
}
|
| 439 |
+
}
|
| 440 |
+
|
| 441 |
+
// Show the welcome page on initial load
|
| 442 |
+
window.onload = () => {
|
| 443 |
+
showView('welcome-view');
|
| 444 |
+
};
|
| 445 |
+
|
| 446 |
+
// =========== CV FORGE SCRIPT ===========
|
| 447 |
+
(function() {
|
| 448 |
+
const instructionsBtn = document.getElementById('cv_instructionsBtn');
|
| 449 |
+
const instructionsPanel = document.getElementById('cv_instructionsPanel');
|
| 450 |
+
const generateBtn = document.getElementById('cv_generateBtn');
|
| 451 |
+
const results = document.getElementById('cv_results');
|
| 452 |
+
const downloadPdfBtn = document.getElementById('cv_downloadPdfBtn');
|
| 453 |
+
const downloadWordBtn = document.getElementById('cv_downloadWordBtn');
|
| 454 |
+
const downloadTxtBtn = document.getElementById('cv_downloadTxtBtn');
|
| 455 |
+
const printBtn = document.getElementById('cv_printBtn');
|
| 456 |
+
|
| 457 |
+
instructionsBtn.addEventListener('click', () => instructionsPanel.classList.toggle('visible'));
|
| 458 |
+
generateBtn.addEventListener('click', cv_generateCv);
|
| 459 |
+
downloadPdfBtn.addEventListener('click', cv_handlePdfDownload);
|
| 460 |
+
downloadWordBtn.addEventListener('click', cv_handleWordDownload);
|
| 461 |
+
downloadTxtBtn.addEventListener('click', cv_handleTxtDownload);
|
| 462 |
+
printBtn.addEventListener('click', cv_handlePrint);
|
| 463 |
+
|
| 464 |
+
document.getElementById('cv-forge-view').addEventListener('click', function(e) {
|
| 465 |
+
if (e.target && e.target.classList.contains('remove-btn')) {
|
| 466 |
+
e.target.closest('.dynamic-section-item').remove();
|
| 467 |
+
}
|
| 468 |
+
});
|
| 469 |
+
|
| 470 |
+
function cv_updateButtons() {
|
| 471 |
+
const hasResults = results.hasAttribute('data-populated');
|
| 472 |
+
downloadPdfBtn.disabled = !hasResults;
|
| 473 |
+
downloadWordBtn.disabled = !hasResults;
|
| 474 |
+
downloadTxtBtn.disabled = !hasResults;
|
| 475 |
+
printBtn.disabled = !hasResults;
|
| 476 |
+
}
|
| 477 |
+
|
| 478 |
+
window.cv_addDynamicEntry = function(type) {
|
| 479 |
+
const container = document.getElementById(`cv_${type}Section`);
|
| 480 |
+
const newItem = document.createElement('div');
|
| 481 |
+
newItem.classList.add('dynamic-section-item');
|
| 482 |
+
let html = '';
|
| 483 |
+
if (type === 'experience') {
|
| 484 |
+
html = `<button type="button" class="remove-btn" title="Remove Entry">X</button><div class="form-grid"><div class="form-group"><label>Job Title</label><input type="text" class="job-title" placeholder="e.g., Senior Developer"></div><div class="form-group"><label>Company</label><input type="text" class="company" placeholder="e.g., Tech Solutions Inc."></div><div class="form-group"><label>Start Date</label><input type="date" class="start-date"></div><div class="form-group"><label>End Date</label><input type="date" class="end-date"></div><div class="form-group full-width"><label>Responsibilities</label><textarea class="description" placeholder="Describe your role..."></textarea></div></div>`;
|
| 485 |
+
} else if (type === 'education') {
|
| 486 |
+
html = `<button type="button" class="remove-btn" title="Remove Entry">X</button><div class="form-grid"><div class="form-group"><label>Degree / Certificate</label><input type="text" class="degree" placeholder="e.g., B.S. in Computer Science"></div><div class="form-group"><label>School / Institution</label><input type="text" class="school" placeholder="e.g., University of Technology"></div><div class="form-group"><label>Start Date</label><input type="date" class="start-date"></div><div class="form-group"><label>End Date</label><input type="date" class="end-date"></div></div>`;
|
| 487 |
+
} else if (type === 'references') {
|
| 488 |
+
html = `<button type="button" class="remove-btn" title="Remove Entry">X</button><div class="form-grid"><div class="form-group"><label>Reference Name</label><input type="text" class="ref-name" placeholder="e.g., John Smith"></div><div class="form-group"><label>Contact Info</label><input type="text" class="ref-contact" placeholder="e.g., j.smith@email.com"></div><div class="form-group full-width"><label>Relationship</label><input type="text" class="ref-relation" placeholder="e.g., Former Manager"></div></div>`;
|
| 489 |
+
}
|
| 490 |
+
newItem.innerHTML = html;
|
| 491 |
+
container.appendChild(newItem);
|
| 492 |
+
}
|
| 493 |
+
|
| 494 |
+
function cv_formatDate(dateString) {
|
| 495 |
+
if (!dateString) return 'Present';
|
| 496 |
+
const date = new Date(dateString);
|
| 497 |
+
return date.toLocaleDateString('en-US', { year: 'numeric', month: 'long' });
|
| 498 |
+
}
|
| 499 |
+
|
| 500 |
+
function cv_generateCv() {
|
| 501 |
+
let html = '<div class="cv-container">';
|
| 502 |
+
const name = document.getElementById('cv_fullName').value;
|
| 503 |
+
const phone = document.getElementById('cv_phone').value;
|
| 504 |
+
const email = document.getElementById('cv_email').value;
|
| 505 |
+
const address = document.getElementById('cv_address').value;
|
| 506 |
+
html += `<div class="cv-header"><h1 class="cv-name">${name}</h1><div class="cv-contact">${address ? address + ' | ' : ''}${phone ? phone + ' | ' : ''}${email ? `<a href="mailto:${email}">${email}</a>` : ''}</div></div>`;
|
| 507 |
+
const about = document.getElementById('cv_about').value;
|
| 508 |
+
if (about) html += `<div class="cv-section"><h2 class="cv-section-title">Professional Summary</h2><p>${about.replace(/\n/g, '<br>')}</p></div>`;
|
| 509 |
+
const workItems = document.querySelectorAll('#cv_workExperienceSection .dynamic-section-item');
|
| 510 |
+
if (workItems.length > 0) {
|
| 511 |
+
html += '<div class="cv-section"><h2 class="cv-section-title">Work Experience</h2>';
|
| 512 |
+
workItems.forEach(item => { html += `<div class="cv-item"><span class="cv-item-dates">${cv_formatDate(item.querySelector('.start-date').value)} - ${cv_formatDate(item.querySelector('.end-date').value)}</span><div class="cv-item-title">${item.querySelector('.job-title').value}</div><div class="cv-item-subtitle">${item.querySelector('.company').value}</div><div class="cv-item-description">${item.querySelector('.description').value.replace(/\n/g, '<br>')}</div></div>`; });
|
| 513 |
+
html += '</div>';
|
| 514 |
+
}
|
| 515 |
+
const eduItems = document.querySelectorAll('#cv_educationSection .dynamic-section-item');
|
| 516 |
+
if (eduItems.length > 0) {
|
| 517 |
+
html += '<div class="cv-section"><h2 class="cv-section-title">Education</h2>';
|
| 518 |
+
eduItems.forEach(item => { html += `<div class="cv-item"><span class="cv-item-dates">${cv_formatDate(item.querySelector('.start-date').value)} - ${cv_formatDate(item.querySelector('.end-date').value)}</span><div class="cv-item-title">${item.querySelector('.degree').value}</div><div class="cv-item-subtitle">${item.querySelector('.school').value}</div></div>`; });
|
| 519 |
+
html += '</div>';
|
| 520 |
+
}
|
| 521 |
+
const skills = document.getElementById('cv_skills').value;
|
| 522 |
+
if (skills) {
|
| 523 |
+
html += '<div class="cv-section"><h2 class="cv-section-title">Skills</h2><ul class="cv-skills-list">';
|
| 524 |
+
skills.split(',').forEach(skill => { html += `<li>${skill.trim()}</li>`; });
|
| 525 |
+
html += '</ul></div>';
|
| 526 |
+
}
|
| 527 |
+
const accomplishments = document.getElementById('cv_accomplishments').value;
|
| 528 |
+
if(accomplishments){
|
| 529 |
+
html += '<div class="cv-section"><h2 class="cv-section-title">Key Accomplishments</h2><ul>';
|
| 530 |
+
accomplishments.split('\n').forEach(acc => { if(acc.trim() !== '') html += `<li>${acc.trim()}</li>`; });
|
| 531 |
+
html += '</ul></div>';
|
| 532 |
+
}
|
| 533 |
+
const refItems = document.querySelectorAll('#cv_referencesSection .dynamic-section-item');
|
| 534 |
+
if (refItems.length > 0) {
|
| 535 |
+
html += '<div class="cv-section"><h2 class="cv-section-title">References</h2>';
|
| 536 |
+
refItems.forEach(item => { html += `<div class="cv-item"><div class="cv-item-title">${item.querySelector('.ref-name').value}</div><div class="cv-item-subtitle">${item.querySelector('.ref-relation').value}</div><div class="cv-item-description">${item.querySelector('.ref-contact').value}</div></div>`; });
|
| 537 |
+
html += '</div>';
|
| 538 |
+
}
|
| 539 |
+
html += '</div>';
|
| 540 |
+
results.innerHTML = html;
|
| 541 |
+
results.setAttribute('contenteditable', 'true');
|
| 542 |
+
results.setAttribute('data-populated', 'true');
|
| 543 |
+
cv_updateButtons();
|
| 544 |
+
}
|
| 545 |
+
|
| 546 |
+
function cv_handlePdfDownload() {
|
| 547 |
+
const element = results;
|
| 548 |
+
const opt = { margin: [0.5, 0.5, 0.5, 0.5], filename: 'my-cv.pdf', image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 2, useCORS: true, logging: false }, jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' } };
|
| 549 |
+
element.style.color = '#333';
|
| 550 |
+
element.querySelectorAll('.cv-name, .cv-section-title').forEach(el => el.style.color = '#0077b5');
|
| 551 |
+
element.querySelectorAll('.cv-contact, .cv-item-subtitle, .cv-item-dates').forEach(el => el.style.color = '#555');
|
| 552 |
+
html2pdf().from(element).set(opt).save().then(() => {
|
| 553 |
+
element.style.color = '';
|
| 554 |
+
element.querySelectorAll('.cv-name, .cv-section-title, .cv-contact, .cv-item-subtitle, .cv-item-dates').forEach(el => el.style.color = '');
|
| 555 |
+
});
|
| 556 |
+
}
|
| 557 |
+
function cv_handleWordDownload() {
|
| 558 |
+
const sourceHTML = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'><head><meta charset='utf-8'><title>CV Export</title><style>body{font-family:Calibri, sans-serif;} .cv-section-title{color:#0077b5;}</style></head><body>" + results.innerHTML + "<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=Inambao/text-to-document-area" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body></html>";
|
| 559 |
+
const source = 'data:application/vnd.ms-word;charset=utf-8,' + encodeURIComponent(sourceHTML);
|
| 560 |
+
const fileDownload = document.createElement("a");
|
| 561 |
+
document.body.appendChild(fileDownload);
|
| 562 |
+
fileDownload.href = source;
|
| 563 |
+
fileDownload.download = 'my-cv.doc';
|
| 564 |
+
fileDownload.click();
|
| 565 |
+
document.body.removeChild(fileDownload);
|
| 566 |
+
}
|
| 567 |
+
function cv_handleTxtDownload() {
|
| 568 |
+
const blob = new Blob([results.innerText], { type: 'text/plain' });
|
| 569 |
+
const url = URL.createObjectURL(blob);
|
| 570 |
+
const a = document.createElement('a');
|
| 571 |
+
a.href = url;
|
| 572 |
+
a.download = 'my-cv.txt';
|
| 573 |
+
document.body.appendChild(a);
|
| 574 |
+
a.click();
|
| 575 |
+
document.body.removeChild(a);
|
| 576 |
+
URL.revokeObjectURL(url);
|
| 577 |
+
}
|
| 578 |
+
function cv_handlePrint() {
|
| 579 |
+
const contentToPrint = results.innerHTML;
|
| 580 |
+
const printWindow = window.open('', '_blank');
|
| 581 |
+
printWindow.document.write(`<!DOCTYPE html><html><head><title>Print CV</title><style>@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap');@page{size:A4;margin:1.5cm;}body{font-family:'Poppins',sans-serif;line-height:1.5;color:#333;}h1,h2,h3{font-family:'Poppins',sans-serif;font-weight:700;color:#000;}.cv-container{padding:0;}.cv-header{text-align:center;margin-bottom:25px;}.cv-name{font-size:2.2em;color:#0077b5;margin:0;}.cv-contact{font-size:.9em;color:#555;}.cv-contact a{color:#0077b5;text-decoration:none;}.cv-section{margin-bottom:20px;page-break-inside:avoid;}.cv-section-title{font-size:1.4em;color:#0077b5;border-bottom:2px solid #0077b5;padding-bottom:5px;margin-bottom:15px;}.cv-item{margin-bottom:15px;}.cv-item-title{font-size:1.1em;font-weight:700;}.cv-item-subtitle{font-size:1em;font-style:italic;color:#555;}.cv-item-dates{float:right;font-style:italic;color:#555;}.cv-item-description{margin-top:5px;padding-left:20px;}.cv-skills-list{list-style:none;padding:0;column-count:2;}</style></head><body>${contentToPrint}</body></html>`);
|
| 582 |
+
printWindow.document.close();
|
| 583 |
+
printWindow.focus();
|
| 584 |
+
setTimeout(() => { printWindow.print(); printWindow.close(); }, 500);
|
| 585 |
+
}
|
| 586 |
+
cv_updateButtons();
|
| 587 |
+
cv_addDynamicEntry('experience');
|
| 588 |
+
cv_addDynamicEntry('education');
|
| 589 |
+
})();
|
| 590 |
+
|
| 591 |
+
|
| 592 |
+
// =========== TEXTIFY PRO SCRIPT ===========
|
| 593 |
+
(function() {
|
| 594 |
+
const fileInput = document.getElementById('textify_fileInput');
|
| 595 |
+
const uploadArea = document.getElementById('textify_uploadArea');
|
| 596 |
+
const preview = document.getElementById('textify_preview');
|
| 597 |
+
const results = document.getElementById('textify_results');
|
| 598 |
+
const marginControl = document.getElementById('textify_marginControl');
|
| 599 |
+
const convertBtn = document.getElementById('textify_convertBtn');
|
| 600 |
+
const instructionsBtn = document.getElementById('textify_instructionsBtn');
|
| 601 |
+
const instructionsPanel = document.getElementById('textify_instructionsPanel');
|
| 602 |
+
const settingsBtn = document.getElementById('textify_settingsBtn');
|
| 603 |
+
const settingsMenu = document.getElementById('textify_settingsMenu');
|
| 604 |
+
const closeSettingsBtn = document.getElementById('textify_closeSettingsBtn');
|
| 605 |
+
const layoutRadios = document.querySelectorAll('input[name="layout"]');
|
| 606 |
+
const downloadPdfBtn = document.getElementById('textify_downloadPdfBtn');
|
| 607 |
+
const downloadWordBtn = document.getElementById('textify_downloadWordBtn');
|
| 608 |
+
const downloadTxtBtn = document.getElementById('textify_downloadTxtBtn');
|
| 609 |
+
const printBtn = document.getElementById('textify_printBtn');
|
| 610 |
+
|
| 611 |
+
window.textify_fileInput = fileInput;
|
| 612 |
+
const API_KEY = "AIzaSyBu-tRMTlTKxu2pauDt40f7ibyRcjYtQ7U"; // NOTE: This is a placeholder key.
|
| 613 |
+
const MODEL_ID = "gemini-1.5-flash-latest";
|
| 614 |
+
const API_URL = `https://generativelanguage.googleapis.com/v1beta/models/${MODEL_ID}:generateContent?key=${API_KEY}`;
|
| 615 |
+
let uploadedImages = [];
|
| 616 |
+
let dragSrcEl = null;
|
| 617 |
+
|
| 618 |
+
fileInput.addEventListener('change', (e) => { textify_addFiles(e.target.files); fileInput.value = ''; });
|
| 619 |
+
uploadArea.addEventListener('dragover', (e) => { e.preventDefault(); uploadArea.classList.add('dragover'); });
|
| 620 |
+
uploadArea.addEventListener('dragleave', () => uploadArea.classList.remove('dragover'));
|
| 621 |
+
uploadArea.addEventListener('drop', (e) => { e.preventDefault(); uploadArea.classList.remove('dragover'); textify_addFiles(e.dataTransfer.files); });
|
| 622 |
+
instructionsBtn.addEventListener('click', () => instructionsPanel.classList.toggle('visible'));
|
| 623 |
+
settingsBtn.addEventListener('click', () => settingsMenu.classList.add('visible'));
|
| 624 |
+
closeSettingsBtn.addEventListener('click', () => settingsMenu.classList.remove('visible'));
|
| 625 |
+
document.addEventListener('click', (e) => { if (!settingsMenu.contains(e.target) && !settingsBtn.contains(e.target)) { settingsMenu.classList.remove('visible'); } });
|
| 626 |
+
marginControl.addEventListener('input', (e) => { preview.style.gap = e.target.value + 'px'; });
|
| 627 |
+
layoutRadios.forEach(radio => radio.addEventListener('change', (e) => {
|
| 628 |
+
preview.classList.remove('layout-row', 'layout-grid');
|
| 629 |
+
preview.classList.add(`layout-${e.target.value}`);
|
| 630 |
+
}));
|
| 631 |
+
downloadPdfBtn.addEventListener('click', textify_handlePdfDownload);
|
| 632 |
+
downloadWordBtn.addEventListener('click', textify_handleWordDownload);
|
| 633 |
+
downloadTxtBtn.addEventListener('click', textify_handleTxtDownload);
|
| 634 |
+
printBtn.addEventListener('click', textify_handlePrint);
|
| 635 |
+
|
| 636 |
+
function textify_addFiles(files) {
|
| 637 |
+
for (const file of files) { if (file.type.startsWith('image/')) uploadedImages.push(file); }
|
| 638 |
+
textify_renderPreviews();
|
| 639 |
+
textify_updateButtons();
|
| 640 |
+
}
|
| 641 |
+
function textify_renderPreviews() {
|
| 642 |
+
preview.innerHTML = '';
|
| 643 |
+
uploadedImages.forEach((file, index) => {
|
| 644 |
+
const reader = new FileReader();
|
| 645 |
+
reader.onload = () => {
|
| 646 |
+
const img = document.createElement('img');
|
| 647 |
+
img.src = reader.result;
|
| 648 |
+
img.className = 'image-thumb'; img.draggable = true; img.dataset.index = index;
|
| 649 |
+
img.addEventListener('dragstart', textify_handleDragStart);
|
| 650 |
+
img.addEventListener('drop', textify_handleDrop);
|
| 651 |
+
img.addEventListener('dragend', textify_handleDragEnd);
|
| 652 |
+
img.addEventListener('dragover', (e) => e.preventDefault());
|
| 653 |
+
preview.appendChild(img);
|
| 654 |
+
};
|
| 655 |
+
reader.readAsDataURL(file);
|
| 656 |
+
});
|
| 657 |
+
}
|
| 658 |
+
function textify_updateButtons() {
|
| 659 |
+
const hasImages = uploadedImages.length > 0;
|
| 660 |
+
const hasResults = results.hasAttribute('data-populated');
|
| 661 |
+
convertBtn.textContent = hasImages ? `Convert ${uploadedImages.length} Image(s)` : 'Convert to Text';
|
| 662 |
+
convertBtn.disabled = !hasImages;
|
| 663 |
+
downloadPdfBtn.disabled = !hasResults;
|
| 664 |
+
downloadWordBtn.disabled = !hasResults;
|
| 665 |
+
downloadTxtBtn.disabled = !hasResults;
|
| 666 |
+
printBtn.disabled = !hasResults;
|
| 667 |
+
}
|
| 668 |
+
function textify_handleDragStart(e) { dragSrcEl = e.target; e.dataTransfer.effectAllowed = 'move'; e.target.classList.add('dragging'); }
|
| 669 |
+
function textify_handleDrop(e) {
|
| 670 |
+
e.stopPropagation();
|
| 671 |
+
if (dragSrcEl !== e.target) {
|
| 672 |
+
const srcIndex = parseInt(dragSrcEl.dataset.index);
|
| 673 |
+
const tgtIndex = parseInt(e.target.dataset.index);
|
| 674 |
+
const draggedItem = uploadedImages.splice(srcIndex, 1)[0];
|
| 675 |
+
uploadedImages.splice(tgtIndex, 0, draggedItem);
|
| 676 |
+
textify_renderPreviews();
|
| 677 |
+
}
|
| 678 |
+
return false;
|
| 679 |
+
}
|
| 680 |
+
function textify_handleDragEnd(e) { e.target.classList.remove('dragging'); }
|
| 681 |
+
|
| 682 |
+
window.textify_convertImages = async function() {
|
| 683 |
+
if (uploadedImages.length === 0) return;
|
| 684 |
+
results.setAttribute('contenteditable', 'false');
|
| 685 |
+
results.removeAttribute('data-populated');
|
| 686 |
+
textify_updateButtons();
|
| 687 |
+
convertBtn.disabled = true;
|
| 688 |
+
let runningLog = '';
|
| 689 |
+
results.innerHTML = '<p><i>🚀 Starting conversion...</i></p>';
|
| 690 |
+
for (let i = 0; i < uploadedImages.length; i++) {
|
| 691 |
+
const file = uploadedImages[i];
|
| 692 |
+
results.innerHTML = runningLog + `<p><i>⏳ Processing image ${i + 1} of ${uploadedImages.length}...</i></p>`;
|
| 693 |
+
try {
|
| 694 |
+
const imagePart = await textify_fileToGenerativePart(file);
|
| 695 |
+
const extractPrompt = "Extract text from this image. Structure the output as clean, semantic HTML. Use headings, paragraphs, and lists where appropriate. Do not include `<html>`, `<head>`, `<body>`, or ````html` markdown tags. Provide only the raw HTML content for the document body.";
|
| 696 |
+
const requestBody = { contents: [{ parts: [{ text: extractPrompt }, imagePart] }] };
|
| 697 |
+
const response = await fetch(API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody) });
|
| 698 |
+
if (!response.ok) throw new Error(`API Error on image ${i+1}: ${response.statusText}`);
|
| 699 |
+
const data = await response.json();
|
| 700 |
+
const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
|
| 701 |
+
if (text) { runningLog += text + '\n<hr>\n'; }
|
| 702 |
+
else { runningLog += `<p style="color: var(--danger-color);">No text found in ${file.name}.</p><hr>`; }
|
| 703 |
+
} catch (error) {
|
| 704 |
+
console.error('API Error:', error);
|
| 705 |
+
runningLog += `<p style="color: var(--danger-color);">❌ ERROR processing ${file.name}. This may be due to an invalid API key or network issue. Displaying mock data.</p><hr><h3>Mock Text for ${file.name}</h3><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><hr>`;
|
| 706 |
+
}
|
| 707 |
+
}
|
| 708 |
+
results.innerHTML = runningLog;
|
| 709 |
+
results.setAttribute('contenteditable', 'true');
|
| 710 |
+
results.setAttribute('data-populated', 'true');
|
| 711 |
+
convertBtn.textContent = '✅ Conversion Complete!';
|
| 712 |
+
convertBtn.disabled = false;
|
| 713 |
+
textify_updateButtons();
|
| 714 |
+
}
|
| 715 |
+
function textify_fileToGenerativePart(file) {
|
| 716 |
+
return new Promise((resolve, reject) => {
|
| 717 |
+
const reader = new FileReader();
|
| 718 |
+
reader.onloadend = () => resolve({ inlineData: { mimeType: file.type, data: reader.result.split(',')[1] } });
|
| 719 |
+
reader.onerror = (err) => reject(err);
|
| 720 |
+
reader.readAsDataURL(file);
|
| 721 |
+
});
|
| 722 |
+
}
|
| 723 |
+
function textify_handlePdfDownload() {
|
| 724 |
+
const element = results;
|
| 725 |
+
const opt = { margin: [0.5, 0.5, 0.5, 0.5], filename: 'textify-export.pdf', image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 2, useCORS: true }, jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' } };
|
| 726 |
+
html2pdf().from(element).set(opt).save();
|
| 727 |
+
}
|
| 728 |
+
function textify_handleWordDownload() {
|
| 729 |
+
const sourceHTML = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'><head><meta charset='utf-8'><title>Textify Export</title></head><body>" + results.innerHTML + "</body></html>";
|
| 730 |
+
const source = 'data:application/vnd.ms-word;charset=utf-8,' + encodeURIComponent(sourceHTML);
|
| 731 |
+
const fileDownload = document.createElement("a");
|
| 732 |
+
document.body.appendChild(fileDownload); fileDownload.href = source; fileDownload.download = 'textify-export.doc'; fileDownload.click(); document.body.removeChild(fileDownload);
|
| 733 |
+
}
|
| 734 |
+
function textify_handleTxtDownload() {
|
| 735 |
+
const blob = new Blob([results.innerText], { type: 'text/plain' });
|
| 736 |
+
const url = URL.createObjectURL(blob);
|
| 737 |
+
const a = document.createElement('a');
|
| 738 |
+
a.href = url; a.download = 'textify-export.txt'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url);
|
| 739 |
+
}
|
| 740 |
+
function textify_handlePrint() {
|
| 741 |
+
const contentToPrint = results.innerHTML;
|
| 742 |
+
const printWindow = window.open('', '_blank');
|
| 743 |
+
printWindow.document.write(`<!DOCTYPE html><html><head><title>Print</title><style>@import url('https://fonts.googleapis.com/css2?family=Georgia&family=Roboto:wght@400;700&display=swap');@page{size:A4;margin:2cm;}body{font-family:'Georgia',serif;line-height:1.6;color:#333;}h1,h2,h3,h4{font-family:'Roboto',sans-serif;color:#000;}hr{border:none;height:1px;background-color:#ccc;margin:2em 0;}</style></head><body>${contentToPrint}</body></html>`);
|
| 744 |
+
printWindow.document.close();
|
| 745 |
+
printWindow.focus();
|
| 746 |
+
setTimeout(() => { printWindow.print(); printWindow.close(); }, 500);
|
| 747 |
+
}
|
| 748 |
+
textify_updateButtons();
|
| 749 |
+
})();
|
| 750 |
+
|
| 751 |
+
</script>
|
| 752 |
+
</body>
|
| 753 |
+
</html>
|