Spaces:
Running
Running
| <html lang="de"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Deep Web Scraper Pro</title> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| :root { | |
| --bg-primary: #0a0a0f; | |
| --bg-secondary: #12121a; | |
| --bg-tertiary: #1a1a25; | |
| --accent-primary: #00d4ff; | |
| --accent-secondary: #7c3aed; | |
| --accent-gradient: linear-gradient(135deg, #00d4ff 0%, #7c3aed 100%); | |
| --text-primary: #ffffff; | |
| --text-secondary: #a0a0b0; | |
| --border-color: #2a2a3a; | |
| --success: #10b981; | |
| --warning: #f59e0b; | |
| --error: #ef4444; | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; | |
| background: var(--bg-primary); | |
| color: var(--text-primary); | |
| min-height: 100vh; | |
| overflow-x: hidden; | |
| } | |
| /* Animated background */ | |
| body::before { | |
| content: ''; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: | |
| radial-gradient(ellipse at 20% 20%, rgba(0, 212, 255, 0.08) 0%, transparent 50%), | |
| radial-gradient(ellipse at 80% 80%, rgba(124, 58, 237, 0.08) 0%, transparent 50%); | |
| pointer-events: none; | |
| z-index: 0; | |
| } | |
| .container { | |
| max-width: 1600px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| position: relative; | |
| z-index: 1; | |
| } | |
| /* Header */ | |
| header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 20px 0; | |
| border-bottom: 1px solid var(--border-color); | |
| margin-bottom: 30px; | |
| } | |
| .logo { | |
| display: flex; | |
| align-items: center; | |
| gap: 15px; | |
| } | |
| .logo-icon { | |
| width: 50px; | |
| height: 50px; | |
| background: var(--accent-gradient); | |
| border-radius: 12px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 24px; | |
| box-shadow: 0 10px 30px rgba(0, 212, 255, 0.3); | |
| } | |
| .logo-text { | |
| font-size: 24px; | |
| font-weight: 700; | |
| background: var(--accent-gradient); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| } | |
| .header-links { | |
| display: flex; | |
| gap: 20px; | |
| align-items: center; | |
| } | |
| .header-links a { | |
| color: var(--text-secondary); | |
| text-decoration: none; | |
| font-size: 14px; | |
| transition: color 0.3s; | |
| } | |
| .header-links a:hover { | |
| color: var(--accent-primary); | |
| } | |
| /* Main Input Section */ | |
| .input-section { | |
| background: var(--bg-secondary); | |
| border-radius: 20px; | |
| padding: 30px; | |
| margin-bottom: 30px; | |
| border: 1px solid var(--border-color); | |
| box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); | |
| } | |
| .input-tabs { | |
| display: flex; | |
| gap: 10px; | |
| margin-bottom: 20px; | |
| } | |
| .input-tab { | |
| padding: 12px 24px; | |
| background: var(--bg-tertiary); | |
| border: none; | |
| border-radius: 10px; | |
| color: var(--text-secondary); | |
| cursor: pointer; | |
| font-size: 14px; | |
| transition: all 0.3s; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .input-tab.active { | |
| background: var(--accent-gradient); | |
| color: white; | |
| } | |
| .input-tab:hover:not(.active) { | |
| background: var(--bg-primary); | |
| color: var(--text-primary); | |
| } | |
| .input-wrapper { | |
| display: flex; | |
| gap: 15px; | |
| } | |
| .url-input { | |
| flex: 1; | |
| padding: 16px 20px; | |
| background: var(--bg-primary); | |
| border: 2px solid var(--border-color); | |
| border-radius: 12px; | |
| color: var(--text-primary); | |
| font-size: 16px; | |
| outline: none; | |
| transition: all 0.3s; | |
| } | |
| .url-input:focus { | |
| border-color: var(--accent-primary); | |
| box-shadow: 0 0 20px rgba(0, 212, 255, 0.2); | |
| } | |
| .url-input::placeholder { | |
| color: var(--text-secondary); | |
| } | |
| .scrape-btn { | |
| padding: 16px 40px; | |
| background: var(--accent-gradient); | |
| border: none; | |
| border-radius: 12px; | |
| color: white; | |
| font-size: 16px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| white-space: nowrap; | |
| } | |
| .scrape-btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 30px rgba(0, 212, 255, 0.4); | |
| } | |
| .scrape-btn:disabled { | |
| opacity: 0.5; | |
| cursor: not-allowed; | |
| transform: none; | |
| } | |
| /* Code Input Area */ | |
| .code-input-area { | |
| display: none; | |
| margin-top: 20px; | |
| } | |
| .code-input-area.active { | |
| display: block; | |
| } | |
| .code-textarea { | |
| width: 100%; | |
| min-height: 200px; | |
| padding: 20px; | |
| background: var(--bg-primary); | |
| border: 2px solid var(--border-color); | |
| border-radius: 12px; | |
| color: var(--text-primary); | |
| font-family: 'Fira Code', 'Consolas', monospace; | |
| font-size: 14px; | |
| resize: vertical; | |
| outline: none; | |
| transition: all 0.3s; | |
| } | |
| .code-textarea:focus { | |
| border-color: var(--accent-primary); | |
| } | |
| /* Progress Section */ | |
| .progress-section { | |
| display: none; | |
| margin: 30px 0; | |
| padding: 30px; | |
| background: var(--bg-secondary); | |
| border-radius: 20px; | |
| border: 1px solid var(--border-color); | |
| } | |
| .progress-section.active { | |
| display: block; | |
| animation: fadeIn 0.5s ease; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(20px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .progress-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| } | |
| .progress-title { | |
| font-size: 18px; | |
| font-weight: 600; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .progress-percentage { | |
| font-size: 32px; | |
| font-weight: 700; | |
| background: var(--accent-gradient); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| } | |
| .progress-bar-container { | |
| background: var(--bg-primary); | |
| border-radius: 10px; | |
| height: 20px; | |
| overflow: hidden; | |
| margin-bottom: 15px; | |
| } | |
| .progress-bar { | |
| height: 100%; | |
| background: var(--accent-gradient); | |
| border-radius: 10px; | |
| width: 0%; | |
| transition: width 0.3s ease; | |
| position: relative; | |
| } | |
| .progress-bar::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent); | |
| animation: shimmer 1.5s infinite; | |
| } | |
| @keyframes shimmer { | |
| 0% { transform: translateX(-100%); } | |
| 100% { transform: translateX(100%); } | |
| } | |
| .progress-status { | |
| color: var(--text-secondary); | |
| font-size: 14px; | |
| } | |
| .progress-stats { | |
| display: flex; | |
| gap: 30px; | |
| margin-top: 20px; | |
| flex-wrap: wrap; | |
| } | |
| .stat-item { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| padding: 10px 15px; | |
| background: var(--bg-tertiary); | |
| border-radius: 10px; | |
| } | |
| .stat-icon { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 10px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 18px; | |
| } | |
| .stat-icon.js { background: rgba(247, 223, 30, 0.2); color: #f7df1e; } | |
| .stat-icon.css { background: rgba(38, 77, 228, 0.2); color: #264de4; } | |
| .stat-icon.pages { background: rgba(16, 185, 129, 0.2); color: var(--success); } | |
| .stat-info { | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .stat-label { | |
| font-size: 12px; | |
| color: var(--text-secondary); | |
| } | |
| .stat-value { | |
| font-size: 18px; | |
| font-weight: 600; | |
| } | |
| /* Results Section */ | |
| .results-section { | |
| display: none; | |
| } | |
| .results-section.active { | |
| display: block; | |
| } | |
| .results-grid { | |
| display: grid; | |
| grid-template-columns: 350px 1fr; | |
| gap: 30px; | |
| } | |
| @media (max-width: 1200px) { | |
| .results-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| /* Links Panel */ | |
| .links-panel { | |
| background: var(--bg-secondary); | |
| border-radius: 20px; | |
| border: 1px solid var(--border-color); | |
| overflow: hidden; | |
| } | |
| .panel-header { | |
| padding: 20px; | |
| border-bottom: 1px solid var(--border-color); | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .panel-title { | |
| font-size: 18px; | |
| font-weight: 600; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .links-count { | |
| background: var(--accent-gradient); | |
| padding: 4px 12px; | |
| border-radius: 20px; | |
| font-size: 14px; | |
| font-weight: 600; | |
| } | |
| .links-filter { | |
| display: flex; | |
| gap: 8px; | |
| } | |
| .filter-btn { | |
| padding: 8px 16px; | |
| background: var(--bg-tertiary); | |
| border: none; | |
| border-radius: 8px; | |
| color: var(--text-secondary); | |
| cursor: pointer; | |
| font-size: 13px; | |
| transition: all 0.3s; | |
| } | |
| .filter-btn.active { | |
| background: var(--accent-primary); | |
| color: var(--bg-primary); | |
| } | |
| .links-list { | |
| max-height: 600px; | |
| overflow-y: auto; | |
| padding: 10px; | |
| } | |
| .link-item { | |
| padding: 15px; | |
| background: var(--bg-tertiary); | |
| border-radius: 12px; | |
| margin-bottom: 10px; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| border: 2px solid transparent; | |
| } | |
| .link-item:hover { | |
| border-color: var(--accent-primary); | |
| transform: translateX(5px); | |
| } | |
| .link-item.selected { | |
| border-color: var(--accent-primary); | |
| background: rgba(0, 212, 255, 0.1); | |
| } | |
| .link-type { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 6px; | |
| padding: 4px 10px; | |
| border-radius: 6px; | |
| font-size: 12px; | |
| font-weight: 600; | |
| margin-bottom: 8px; | |
| } | |
| .link-type.js { | |
| background: rgba(247, 223, 30, 0.2); | |
| color: #f7df1e; | |
| } | |
| .link-type.css { | |
| background: rgba(38, 77, 228, 0.2); | |
| color: #264de4; | |
| } | |
| .link-url { | |
| font-size: 13px; | |
| color: var(--text-primary); | |
| word-break: break-all; | |
| font-family: 'Fira Code', monospace; | |
| } | |
| .link-size { | |
| font-size: 12px; | |
| color: var(--text-secondary); | |
| margin-top: 5px; | |
| } | |
| /* Preview Panel */ | |
| .preview-panel { | |
| background: var(--bg-secondary); | |
| border-radius: 20px; | |
| border: 1px solid var(--border-color); | |
| overflow: hidden; | |
| } | |
| .preview-header { | |
| padding: 20px; | |
| border-bottom: 1px solid var(--border-color); | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| flex-wrap: wrap; | |
| gap: 15px; | |
| } | |
| .preview-title { | |
| font-size: 18px; | |
| font-weight: 600; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .preview-actions { | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .action-btn { | |
| padding: 10px 20px; | |
| background: var(--bg-tertiary); | |
| border: 1px solid var(--border-color); | |
| border-radius: 10px; | |
| color: var(--text-primary); | |
| cursor: pointer; | |
| font-size: 14px; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| transition: all 0.3s; | |
| } | |
| .action-btn:hover { | |
| background: var(--accent-primary); | |
| color: var(--bg-primary); | |
| border-color: var(--accent-primary); | |
| } | |
| .preview-content { | |
| padding: 20px; | |
| min-height: 500px; | |
| } | |
| .preview-frame { | |
| width: 100%; | |
| height: 500px; | |
| border: none; | |
| border-radius: 12px; | |
| background: var(--bg-primary); | |
| } | |
| .preview-empty { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| height: 400px; | |
| color: var(--text-secondary); | |
| } | |
| .preview-empty i { | |
| font-size: 60px; | |
| margin-bottom: 20px; | |
| opacity: 0.5; | |
| } | |
| /* CSS Transform Controls */ | |
| .transform-controls { | |
| display: none; | |
| padding: 20px; | |
| background: var(--bg-tertiary); | |
| border-top: 1px solid var(--border-color); | |
| } | |
| .transform-controls.active { | |
| display: block; | |
| } | |
| .transform-title { | |
| font-size: 16px; | |
| font-weight: 600; | |
| margin-bottom: 15px; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| color: var(--accent-primary); | |
| } | |
| .transform-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); | |
| gap: 15px; | |
| } | |
| .transform-item { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 8px; | |
| } | |
| .transform-label { | |
| font-size: 13px; | |
| color: var(--text-secondary); | |
| display: flex; | |
| justify-content: space-between; | |
| } | |
| .transform-value { | |
| color: var(--accent-primary); | |
| font-family: monospace; | |
| } | |
| .transform-slider { | |
| -webkit-appearance: none; | |
| width: 100%; | |
| height: 6px; | |
| background: var(--bg-primary); | |
| border-radius: 3px; | |
| outline: none; | |
| } | |
| .transform-slider::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| width: 18px; | |
| height: 18px; | |
| background: var(--accent-gradient); | |
| border-radius: 50%; | |
| cursor: pointer; | |
| box-shadow: 0 2px 10px rgba(0, 212, 255, 0.5); | |
| } | |
| .transform-presets { | |
| display: flex; | |
| gap: 10px; | |
| margin-top: 15px; | |
| flex-wrap: wrap; | |
| } | |
| .preset-btn { | |
| padding: 8px 16px; | |
| background: var(--bg-secondary); | |
| border: 1px solid var(--border-color); | |
| border-radius: 8px; | |
| color: var(--text-secondary); | |
| cursor: pointer; | |
| font-size: 13px; | |
| transition: all 0.3s; | |
| } | |
| .preset-btn:hover { | |
| border-color: var(--accent-primary); | |
| color: var(--accent-primary); | |
| } | |
| /* Stored Files Section */ | |
| .stored-section { | |
| margin-top: 30px; | |
| background: var(--bg-secondary); | |
| border-radius: 20px; | |
| border: 1px solid var(--border-color); | |
| overflow: hidden; | |
| } | |
| .stored-header { | |
| padding: 20px; | |
| border-bottom: 1px solid var(--border-color); | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .stored-title { | |
| font-size: 18px; | |
| font-weight: 600; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .stored-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); | |
| gap: 20px; | |
| padding: 20px; | |
| } | |
| .stored-card { | |
| background: var(--bg-tertiary); | |
| border-radius: 16px; | |
| overflow: hidden; | |
| border: 2px solid var(--border-color); | |
| transition: all 0.3s; | |
| } | |
| .stored-card:hover { | |
| border-color: var(--accent-primary); | |
| transform: translateY(-5px); | |
| box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3); | |
| } | |
| .stored-preview { | |
| height: 150px; | |
| background: var(--bg-primary); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| border-bottom: 1px solid var(--border-color); | |
| } | |
| .stored-preview iframe { | |
| width: 100%; | |
| height: 100%; | |
| border: none; | |
| } | |
| .stored-info { | |
| padding: 15px; | |
| } | |
| .stored-filename { | |
| font-size: 14px; | |
| font-weight: 600; | |
| margin-bottom: 5px; | |
| word-break: break-all; | |
| } | |
| .stored-meta { | |
| font-size: 12px; | |
| color: var(--text-secondary); | |
| display: flex; | |
| justify-content: space-between; | |
| } | |
| .stored-actions { | |
| padding: 10px 15px; | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .stored-btn { | |
| flex: 1; | |
| padding: 8px; | |
| background: var(--bg-secondary); | |
| border: none; | |
| border-radius: 8px; | |
| color: var(--text-secondary); | |
| cursor: pointer; | |
| font-size: 12px; | |
| transition: all 0.3s; | |
| } | |
| .stored-btn:hover { | |
| background: var(--accent-primary); | |
| color: var(--bg-primary); | |
| } | |
| /* Scrollbar */ | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| height: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: var(--bg-primary); | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: var(--border-color); | |
| border-radius: 4px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: var(--accent-primary); | |
| } | |
| /* Toast Notifications */ | |
| .toast-container { | |
| position: fixed; | |
| top: 20px; | |
| right: 20px; | |
| z-index: 1000; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 10px; | |
| } | |
| .toast { | |
| padding: 15px 20px; | |
| background: var(--bg-secondary); | |
| border: 1px solid var(--border-color); | |
| border-radius: 12px; | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| animation: slideIn 0.3s ease; | |
| box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); | |
| } | |
| @keyframes slideIn { | |
| from { transform: translateX(100%); opacity: 0; } | |
| to { transform: translateX(0); opacity: 1; } | |
| } | |
| .toast.success { border-left: 4px solid var(--success); } | |
| .toast.error { border-left: 4px solid var(--error); } | |
| .toast.warning { border-left: 4px solid var(--warning); } | |
| .toast-icon { | |
| font-size: 20px; | |
| } | |
| .toast.success .toast-icon { color: var(--success); } | |
| .toast.error .toast-icon { color: var(--error); } | |
| .toast.warning .toast-icon { color: var(--warning); } | |
| /* Loading Animation */ | |
| .loading-spinner { | |
| width: 20px; | |
| height: 20px; | |
| border: 2px solid transparent; | |
| border-top-color: white; | |
| border-radius: 50%; | |
| animation: spin 0.8s linear infinite; | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| /* Empty State */ | |
| .empty-state { | |
| text-align: center; | |
| padding: 60px 20px; | |
| color: var(--text-secondary); | |
| } | |
| .empty-state i { | |
| font-size: 80px; | |
| margin-bottom: 20px; | |
| opacity: 0.3; | |
| } | |
| .empty-state h3 { | |
| font-size: 20px; | |
| margin-bottom: 10px; | |
| color: var(--text-primary); | |
| } | |
| /* Responsive */ | |
| @media (max-width: 768px) { | |
| .container { | |
| padding: 10px; | |
| } | |
| header { | |
| flex-direction: column; | |
| gap: 15px; | |
| } | |
| .input-wrapper { | |
| flex-direction: column; | |
| } | |
| .scrape-btn { | |
| width: 100%; | |
| justify-content: center; | |
| } | |
| .progress-stats { | |
| flex-direction: column; | |
| } | |
| .transform-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <header> | |
| <div class="logo"> | |
| <div class="logo-icon"> | |
| <i class="fas fa-spider"></i> | |
| </div> | |
| <span class="logo-text">Deep Web Scraper Pro</span> | |
| </div> | |
| <div class="header-links"> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">Built with anycoder</a> | |
| <a href="#"><i class="fas fa-cog"></i> Settings</a> | |
| </div> | |
| </header> | |
| <section class="input-section"> | |
| <div class="input-tabs"> | |
| <button class="input-tab active" data-tab="url"> | |
| <i class="fas fa-link"></i> URL Input | |
| </button> | |
| <button class="input-tab" data-tab="source"> | |
| <i class="fas fa-code"></i> Source Code | |
| </button> | |
| </div> | |
| <div class="input-wrapper" id="url-input-wrapper"> | |
| <input type="text" class="url-input" id="urlInput" placeholder="Enter website URL (e.g., https://example.com)"> | |
| <button class="scrape-btn" id="scrapeBtn"> | |
| <i class="fas fa-search"></i> | |
| Start Scraping | |
| </button> | |
| </div> | |
| <div class="code-input-area" id="code-input-area"> | |
| <textarea class="code-textarea" id="sourceCodeInput" placeholder="Paste your HTML source code here..."></textarea> | |
| <button class="scrape-btn" id="scrapeSourceBtn" style="margin-top: 15px;"> | |
| <i class="fas fa-search"></i> | |
| Analyze Source | |
| </button> | |
| </div> | |
| </section> | |
| <section class="progress-section" id="progressSection"> | |
| <div class="progress-header"> | |
| <div class="progress-title"> | |
| <i class="fas fa-spinner fa-spin"></i> | |
| <span>Scraping in Progress...</span> | |
| </div> | |
| <div class="progress-percentage" id="progressPercent">0%</div> | |
| </div> | |
| <div class="progress-bar-container"> | |
| <div class="progress-bar" id="progressBar"></div> | |
| </div> | |
| <div class="progress-status" id="progressStatus">Initializing scraper...</div> | |
| <div class="progress-stats"> | |
| <div class="stat-item"> | |
| <div class="stat-icon pages"> | |
| <i class="fas fa-globe"></i> | |
| </div> | |
| <div class="stat-info"> | |
| <span class="stat-label">Pages Scraped</span> | |
| <span class="stat-value" id="pagesCount">0</span> | |
| </div> | |
| </div> | |
| <div class="stat-item"> | |
| <div class="stat-icon js"> | |
| <i class="fab fa-js"></i> | |
| </div> | |
| <div class="stat-info"> | |
| <span class="stat-label">JavaScript Files</span> | |
| <span class="stat-value" id="jsCount">0</span> | |
| </div> | |
| </div> | |
| <div class="stat-item"> | |
| <div class="stat-icon css"> | |
| <i class="fab fa-css3-alt"></i> | |
| </div> | |
| <div class="stat-info"> | |
| <span class="stat-label">CSS Files</span> | |
| <span class="stat-value" id="cssCount">0</span> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <section class="results-section" id="resultsSection"> | |
| <div class="results-grid"> | |
| <div class="links-panel"> | |
| <div class="panel-header"> | |
| <div class="panel-title"> | |
| <i class="fas fa-list"></i> | |
| Extracted Resources | |
| <span class="links-count" id="linksCount">0</span> | |
| </div> | |
| <div class="links-filter"> | |
| <button class="filter-btn active" data-filter="all">All</button> | |
| <button class="filter-btn" data-filter="js">JS</button> | |
| <button class="filter-btn" data-filter="css">CSS</button> | |
| </div> | |
| </div> | |
| <div class="links-list" id="linksList"> | |
| <!-- Links will be inserted here --> | |
| </div> | |
| </div> | |
| <div class="preview-panel"> | |
| <div class="preview-header"> | |
| <div class="preview-title"> | |
| <i class="fas fa-eye"></i> | |
| Preview | |
| <span id="previewFileName" style="color: var(--text-secondary); font-weight: normal; font-size: 14px;"></span> | |
| </div> | |
| <div class="preview-actions"> | |
| <button class="action-btn" id="saveBtn"> | |
| <i class="fas fa-save"></i> Save | |
| </button> | |
| <button class="action-btn" id="downloadBtn"> | |
| <i class="fas fa-download"></i> Download | |
| </button> | |
| <button class="action-btn" id="transformBtn"> | |
| <i class="fas fa-magic"></i> Transform | |
| </button> | |
| </div> | |
| </div> | |
| <div class="preview-content"> | |
| <iframe class="preview-frame" id="previewFrame" sandbox="allow-same-origin"></iframe> | |
| </div> | |
| <div class="transform-controls" id="transformControls"> | |
| <div class="transform-title"> | |
| <i class="fas fa-magic"></i> CSS Transform Controls | |
| </div> | |
| <div class="transform-grid"> | |
| <div class="transform-item"> | |
| <div class="transform-label"> | |
| <span>Translate X</span> | |
| <span class="transform-value" id="translateXVal">0px</span> | |
| </div> | |
| <input type="range" class="transform-slider" id="translateX" min="-200" max="200" value="0"> | |
| </div> | |
| <div class="transform-item"> | |
| <div class="transform-label"> | |
| <span>Translate Y</span> | |
| <span class="transform-value" id="translateYVal">0px</span> | |
| </div> | |
| <input type="range" class="transform-slider" id="translateY" min="-200" max="200" value="0"> | |
| </div> | |
| <div class="transform-item"> | |
| <div class="transform-label"> | |
| <span>Rotate</span> | |
| <span class="transform-value" id="rotateVal">0deg</span> | |
| </div> | |
| <input type="range" class="transform-slider" id="rotate" min="-360" max="360" value="0"> | |
| </div> | |
| <div class="transform-item"> | |
| <div class="transform-label"> | |
| <span>Scale</span> | |
| <span class="transform-value" id="scaleVal">1</span> | |
| </div> | |
| <input type="range" class="transform-slider" id="scale" min="0.1" max="3" step="0.1" value="1"> | |
| </div> | |
| <div class="transform-item"> | |
| <div class="transform-label"> | |
| <span>Skew X</span> | |
| <span class="transform-value" id="skewXVal">0deg</span> | |
| </div> | |
| <input type="range" class="transform-slider" id="skewX" min="-45" max="45" value="0"> | |
| </div> | |
| <div class="transform-item"> | |
| <div class="transform-label"> | |
| <span>Skew Y</span> | |
| <span class="transform-value" id="skewYVal">0deg</span> | |
| </div> | |
| <input type="range" class="transform-slider" id="skewY" min="-45" max="45" value="0"> | |
| </div> | |
| <div class="transform-item"> | |
| <div class="transform-label"> | |
| <span>Perspective</span> | |
| <span class="transform-value" id="perspectiveVal">500px</span> | |
| </div> | |
| <input type="range" class="transform-slider" id="perspective" min="100" max="1000" value="500"> | |
| </div> | |
| <div class="transform-item"> | |
| <div class="transform-label"> | |
| <span>Opacity</span> | |
| <span class="transform-value" id="opacityVal">1</span> | |
| </div> | |
| <input type="range" class="transform-slider" id="opacity" min="0" max="1" step="0.1" value="1"> | |
| </div> | |
| </div> | |
| <div class="transform-presets"> | |
| <button class="preset-btn" data-preset="reset">Reset</button> | |
| <button class="preset-btn" data-preset="flip">Flip</button> | |
| <button class="preset-btn" data-preset="zoom">Zoom In</button> | |
| <button class="preset-btn" data-preset="tilt">3D Tilt</button> | |
| <button class="preset-btn" data-preset="spin">Spin</button> | |
| <button class="preset-btn" data-preset="shake">Shake</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <section class="stored-section" id="storedSection"> | |
| <div class="stored-header"> | |
| <div class="stored-title"> | |
| <i class="fas fa-folder-open"></i> | |
| Saved Files Stream | |
| <span class="links-count" id="storedCount">0</span> | |
| </div> | |
| <button class="action-btn" id="clearStorageBtn"> | |
| <i class="fas fa-trash"></i> Clear All | |
| </button> | |
| </div> | |
| <div class="stored-grid" id="storedGrid"> | |
| <!-- Stored files will be inserted here --> | |
| </div> | |
| </section> | |
| </div> | |
| <div class="toast-container" id="toastContainer"></div> | |
| <script> | |
| // Application State | |
| const state = { | |
| links: [], | |
| selectedLink: null, | |
| storedFiles: [], | |
| isScraping: false | |
| }; | |
| // DOM Elements | |
| const elements = { | |
| urlInput: document.getElementById('urlInput'), | |
| sourceCodeInput: document.getElementById('sourceCodeInput'), | |
| scrapeBtn: document.getElementById('scrapeBtn'), | |
| scrapeSourceBtn: document.getElementById('scrapeSourceBtn'), | |
| progressSection: document.getElementById('progressSection'), | |
| progressBar: document.getElementById('progressBar'), | |
| progressPercent: document.getElementById('progressPercent'), | |
| progressStatus: document.getElementById('progressStatus'), | |
| pagesCount: document.getElementById('pagesCount'), | |
| jsCount: document.getElementById('jsCount'), | |
| cssCount: document.getElementById('cssCount'), | |
| resultsSection: document.getElementById('resultsSection'), | |
| linksList: document.getElementById('linksList'), | |
| linksCount: document.getElementById('linksCount'), | |
| previewFrame: document.getElementById('previewFrame'), | |
| previewFileName: document.getElementById('previewFileName'), | |
| transformControls: document.getElementById('transformControls'), | |
| storedSection: document.getElementById('storedSection'), | |
| storedGrid: document.getElementById('storedGrid'), | |
| storedCount: document.getElementById('storedCount'), | |
| toastContainer: document.getElementById('toastContainer') | |
| }; | |
| // Tab Switching | |
| document.querySelectorAll('.input-tab').forEach(tab => { | |
| tab.addEventListener('click', () => { | |
| document.querySelectorAll('.input-tab').forEach(t => t.classList.remove('active')); | |
| tab.classList.add('active'); | |
| const tabType = tab.dataset.tab; | |
| document.getElementById('url-input-wrapper').style.display = tabType === 'url' ? 'flex' : 'none'; | |
| document.getElementById('code-input-area').classList.toggle('active', tabType === 'source'); | |
| }); | |
| }); | |
| // Filter Buttons | |
| document.querySelectorAll('.filter-btn').forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active')); | |
| btn.classList.add('active'); | |
| renderLinks(btn.dataset.filter); | |
| }); | |
| }); | |
| // Transform Controls | |
| const transformSliders = ['translateX', 'translateY', 'rotate', 'scale', 'skewX', 'skewY', 'perspective', 'opacity']; | |
| transformSliders.forEach(id => { | |
| const slider = document.getElementById(id); | |
| if (slider) { | |
| slider.addEventListener('input', updateTransform); | |
| } | |
| }); | |
| function updateTransform() { | |
| const translateX = document.getElementById('translateX').value; | |
| const translateY = document.getElementById('translateY').value; | |
| const rotate = document.getElementById('rotate').value; | |
| const scale = document.getElementById('scale').value; | |
| const skewX = document.getElementById('skewX').value; | |
| const skewY = document.getElementById('skewY').value; | |
| const perspective = document.getElementById('perspective').value; | |
| const opacity = document.getElementById('opacity').value; | |
| // Update display values | |
| document.getElementById('translateXVal').textContent = translateX + 'px'; | |
| document.getElementById('translateYVal').textContent = translateY + 'px'; | |
| document.getElementById('rotateVal').textContent = rotate + 'deg'; | |
| document.getElementById('scaleVal').textContent = scale; | |
| document.getElementById('skewXVal').textContent = skewX + 'deg'; | |
| document.getElementById('skewYVal').textContent = skewY + 'deg'; | |
| document.getElementById('perspectiveVal').textContent = perspective + 'px'; | |
| document.getElementById('opacityVal').textContent = opacity; | |
| // Apply transform | |
| const transform = `perspective(${perspective}px) translateX(${translateX}px) translateY(${translateY}px) rotate(${rotate}deg) scale(${scale}) skewX(${skewX}deg) skewY(${skewY}deg)`; | |
| elements.previewFrame.style.transform = transform; | |
| elements.previewFrame.style.opacity = opacity; | |
| } | |
| // Preset Buttons | |
| document.querySelectorAll('.preset-btn').forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| const preset = btn.dataset.preset; | |
| applyPreset(preset); | |
| }); | |
| }); | |
| function applyPreset(preset) { | |
| switch(preset) { | |
| case 'reset': | |
| setTransformValues(0, 0, 0, 1, 0, 0, 500, 1); | |
| break; | |
| case 'flip': | |
| setTransformValues(0, 0, 180, 1, 0, 0, 500, 1); | |
| break; | |
| case 'zoom': | |
| setTransformValues(0, 0, 0, 1.5, 0, 0, 500, 1); | |
| break; | |
| case 'tilt': | |
| setTransformValues(0, 0, 0, 1, 20, 20, 500, 1); | |
| break; | |
| case 'spin': | |
| setTransformValues(0, 0, 360, 1, 0, 0, 500, 1); | |
| break; | |
| case 'shake': | |
| setTransformValues(20, 0, 0, 1, 0, 0, 500, 1); | |
| setTimeout(() => setTransformValues(-20, 0, 0, 1, 0, 0, 500, 1), 100); | |
| setTimeout(() => setTransformValues(0, 0, 0, 1, 0, 0, 500, 1), 200); | |
| break; | |
| } | |
| updateTransform(); | |
| } | |
| function setTransformValues(tx, ty, r, s, sx, sy, p, o) { | |
| document.getElementById('translateX').value = tx; | |
| document.getElementById('translateY').value = ty; | |
| document.getElementById('rotate').value = r; | |
| document.getElementById('scale').value = s; | |
| document.getElementById('skewX').value = sx; | |
| document.getElementById('skewY').value = sy; | |
| document.getElementById('perspective').value = p; | |
| document.getElementById('opacity').value = o; | |
| } | |
| // Toggle Transform Controls | |
| document.getElementById('transformBtn').addEventListener('click', () => { | |
| elements.transformControls.classList.toggle('active'); | |
| }); | |
| // Toast Notifications | |
| function showToast(message, type = 'success') { | |
| const toast = document.createElement('div'); | |
| toast.className = `toast ${type}`; | |
| let icon = 'check-circle'; | |
| if (type === 'error') icon = 'exclamation-circle'; | |
| if (type === 'warning') icon = 'exclamation-triangle'; | |
| toast.innerHTML = ` | |
| <i class="fas fa-${icon} toast-icon"></i> | |
| <span>${message}</span> | |
| `; | |
| elements.toastContainer.appendChild(toast); | |
| setTimeout(() => { | |
| toast.style.animation = 'slideIn 0.3s reverse'; | |
| setTimeout(() => toast.remove(), 300); | |
| }, 3000); | |
| } | |
| // Simulated Scraping Process | |
| async function simulateScraping(input, isUrl = true) { | |
| state.isScraping = true; | |
| elements.scrapeBtn.disabled = true; | |
| elements.scrapeBtn.innerHTML = '<div class="loading-spinner"></div> Scraping...'; | |
| elements.progressSection.classList.add('active'); | |
| elements.resultsSection.classList.remove('active'); | |
| const links = []; | |
| // Simulate crawling multiple pages | |
| const pages = isUrl ? 5 : 1; | |
| for (let i = 0; i <= 100; i += 5) { | |
| await delay(100); | |
| updateProgress(i, `Scanning page ${Math.ceil(i/20)} of ${pages}...`); | |
| // Simulate finding links at certain progress points | |
| if (i === 20) { | |
| links.push(...generateMockLinks(input, 'js', 3)); | |
| } | |
| if (i === 40) { | |
| links.push(...generateMockLinks(input, 'css', 2)); | |
| } | |
| if (i === 60) { | |
| links.push(...generateMockLinks(input, 'js', 2)); | |
| } | |
| if (i === 80) { | |
| links.push(...generateMockLinks(input, 'css', 3)); | |
| } | |
| } | |
| state.links = links; | |
| state.isScraping = false; | |
| elements.scrapeBtn.disabled = false; | |
| elements.scrapeBtn.innerHTML = '<i class="fas fa-search"></i> Start Scraping'; | |
| showToast(`Found ${links.length} resources!`, 'success'); | |
| displayResults(); | |
| } | |
| function generateMockLinks(base, type, count) { | |
| const links = []; | |
| const domains = ['jquery.com', 'cdnjs.cloudflare.com', 'unpkg.com', 'google.com']; | |
| for (let i = 0; i < count; i++) { | |
| const domain = domains[Math.floor(Math.random() * domains.length)]; | |
| const version = Math.floor(Math.random() * 10) + 1; | |
| const size = Math.floor(Math.random() * 100) + 10; | |
| if (type === 'js') { | |
| links.push({ | |
| type: 'js', | |
| url: `https://${domain}/ajax/libs/${type}${version}.${i}/lib.min.js`, | |
| size: size + ' KB' | |
| }); | |
| } else { | |
| links.push({ | |
| type: 'css', | |
| url: `https://${domain |