HI7RAI commited on
Commit
10114d5
·
verified ·
1 Parent(s): 0e454c3

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +1193 -1261
index.html CHANGED
@@ -1,1274 +1,1206 @@
1
  <!DOCTYPE html>
2
  <html lang="de">
3
  <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>CodeFlow Pro - Modern File Processor</title>
7
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
8
- <style>
9
- /* ===== MODERN CSS RESET & BASE ===== */
10
- *, *::before, *::after {
11
- box-sizing: border-box;
12
- margin: 0;
13
- padding: 0;
14
- }
15
-
16
- :root {
17
- --primary: #6366f1;
18
- --primary-dark: #4f46e5;
19
- --secondary: #10b981;
20
- --danger: #ef4444;
21
- --warning: #f59e0b;
22
- --dark: #1f2937;
23
- --darker: #111827;
24
- --light: #f9fafb;
25
- --gray: #9ca3af;
26
- --border-radius: 12px;
27
- --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
28
- --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
29
- --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
30
- --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
31
- --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
32
- }
33
-
34
- html {
35
- scroll-behavior: smooth;
36
- }
37
-
38
- body {
39
- font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
40
- background: linear-gradient(135deg, var(--darker) 0%, var(--dark) 100%);
41
- color: var(--light);
42
- min-height: 100vh;
43
- display: grid;
44
- grid-template-rows: auto 1fr;
45
- line-height: 1.6;
46
- }
47
-
48
- /* ===== HEADER ===== */
49
- .header {
50
- background: rgba(31, 41, 55, 0.95);
51
- backdrop-filter: blur(10px);
52
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
53
- padding: 1rem 2rem;
54
- position: sticky;
55
- top: 0;
56
- z-index: 100;
57
- display: flex;
58
- justify-content: space-between;
59
- align-items: center;
60
- flex-wrap: wrap;
61
- gap: 1rem;
62
- }
63
-
64
- .logo-section {
65
- display: flex;
66
- align-items: center;
67
- gap: 0.75rem;
68
- }
69
-
70
- .logo {
71
- width: 40px;
72
- height: 40px;
73
- background: linear-gradient(135deg, var(--primary), var(--secondary));
74
- border-radius: 10px;
75
- display: grid;
76
- place-items: center;
77
- font-weight: bold;
78
- font-size: 1.25rem;
79
- }
80
-
81
- .brand {
82
- font-size: 1.5rem;
83
- font-weight: 700;
84
- background: linear-gradient(135deg, var(--primary), var(--secondary));
85
- -webkit-background-clip: text;
86
- -webkit-text-fill-color: transparent;
87
- }
88
-
89
- .anycoder-link {
90
- background: var(--primary);
91
- color: white;
92
- padding: 0.5rem 1rem;
93
- border-radius: 20px;
94
- text-decoration: none;
95
- font-size: 0.875rem;
96
- font-weight: 600;
97
- transition: var(--transition);
98
- box-shadow: var(--shadow-md);
99
- }
100
-
101
- .anycoder-link:hover {
102
- background: var(--primary-dark);
103
- transform: translateY(-2px);
104
- box-shadow: var(--shadow-lg);
105
- }
106
-
107
- /* ===== NAVIGATION TABS ===== */
108
- .nav-tabs {
109
- display: flex;
110
- gap: 0.5rem;
111
- overflow-x: auto;
112
- scrollbar-width: none;
113
- }
114
-
115
- .nav-tabs::-webkit-scrollbar {
116
- display: none;
117
- }
118
-
119
- .tab-btn {
120
- background: rgba(255, 255, 255, 0.05);
121
- border: 1px solid rgba(255, 255, 255, 0.1);
122
- color: var(--gray);
123
- padding: 0.75rem 1.5rem;
124
- border-radius: 8px;
125
- cursor: pointer;
126
- font-weight: 600;
127
- transition: var(--transition);
128
- white-space: nowrap;
129
- display: flex;
130
- align-items: center;
131
- gap: 0.5rem;
132
- }
133
-
134
- .tab-btn:hover {
135
- background: rgba(255, 255, 255, 0.1);
136
- color: var(--light);
137
- }
138
-
139
- .tab-btn.active {
140
- background: var(--primary);
141
- color: white;
142
- border-color: var(--primary);
143
- box-shadow: var(--shadow-md);
144
- }
145
-
146
- .tab-btn .badge {
147
- background: var(--danger);
148
- color: white;
149
- padding: 0.125rem 0.5rem;
150
- border-radius: 10px;
151
- font-size: 0.75rem;
152
- font-weight: 700;
153
- }
154
-
155
- /* ===== MAIN CONTENT ===== */
156
- .main-content {
157
- padding: 2rem;
158
- container-type: inline-size;
159
- overflow-y: auto;
160
- }
161
-
162
- .tab-panel {
163
- display: none;
164
- animation: fadeIn 0.3s ease-in-out;
165
- }
166
-
167
- .tab-panel.active {
168
- display: block;
169
- }
170
-
171
- @keyframes fadeIn {
172
- from { opacity: 0; transform: translateY(10px); }
173
- to { opacity: 1; transform: translateY(0); }
174
- }
175
-
176
- /* ===== UPLOAD SECTION ===== */
177
- .upload-zone {
178
- background: rgba(255, 255, 255, 0.03);
179
- border: 2px dashed rgba(255, 255, 255, 0.2);
180
- border-radius: var(--border-radius);
181
- padding: 3rem;
182
- text-align: center;
183
- transition: var(--transition);
184
- cursor: pointer;
185
- position: relative;
186
- overflow: hidden;
187
- }
188
-
189
- .upload-zone:hover {
190
- border-color: var(--primary);
191
- background: rgba(99, 102, 241, 0.05);
192
- }
193
-
194
- .upload-zone.dragover {
195
- border-color: var(--secondary);
196
- background: rgba(16, 185, 129, 0.1);
197
- transform: scale(1.02);
198
- }
199
-
200
- .upload-icon {
201
- font-size: 3rem;
202
- color: var(--gray);
203
- margin-bottom: 1rem;
204
- }
205
-
206
- .upload-text {
207
- font-size: 1.25rem;
208
- margin-bottom: 0.5rem;
209
- }
210
-
211
- .upload-hint {
212
- color: var(--gray);
213
- font-size: 0.875rem;
214
- }
215
-
216
- .file-input {
217
- display: none;
218
- }
219
-
220
- .action-buttons {
221
- display: flex;
222
- gap: 1rem;
223
- margin-top: 2rem;
224
- flex-wrap: wrap;
225
- }
226
-
227
- .btn {
228
- background: var(--primary);
229
- color: white;
230
- border: none;
231
- padding: 0.75rem 1.5rem;
232
- border-radius: 8px;
233
- cursor: pointer;
234
- font-weight: 600;
235
- transition: var(--transition);
236
- display: inline-flex;
237
- align-items: center;
238
- gap: 0.5rem;
239
- box-shadow: var(--shadow-sm);
240
- }
241
-
242
- .btn:hover {
243
- background: var(--primary-dark);
244
- transform: translateY(-2px);
245
- box-shadow: var(--shadow-md);
246
- }
247
-
248
- .btn-secondary {
249
- background: var(--secondary);
250
- }
251
-
252
- .btn-secondary:hover {
253
- background: #059669;
254
- }
255
-
256
- .btn-danger {
257
- background: var(--danger);
258
- }
259
-
260
- .btn-danger:hover {
261
- background: #dc2626;
262
- }
263
-
264
- /* ===== MODULE LIST ===== */
265
- .module-grid {
266
- display: grid;
267
- gap: 1.5rem;
268
- grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
269
- margin-top: 2rem;
270
- }
271
-
272
- @container (max-width: 900px) {
273
- .module-grid {
274
- grid-template-columns: 1fr;
275
- }
276
- }
277
-
278
- .module-card {
279
- background: rgba(255, 255, 255, 0.05);
280
- border: 1px solid rgba(255, 255, 255, 0.1);
281
- border-radius: var(--border-radius);
282
- overflow: hidden;
283
- transition: var(--transition);
284
- position: relative;
285
- }
286
-
287
- .module-card:hover {
288
- transform: translateY(-4px);
289
- box-shadow: var(--shadow-xl);
290
- border-color: rgba(99, 102, 241, 0.3);
291
- }
292
-
293
- .module-header {
294
- background: rgba(255, 255, 255, 0.03);
295
- padding: 1rem 1.5rem;
296
- display: flex;
297
- justify-content: space-between;
298
- align-items: center;
299
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
300
- }
301
-
302
- .module-title {
303
- font-weight: 700;
304
- display: flex;
305
- align-items: center;
306
- gap: 0.5rem;
307
- }
308
-
309
- .module-status {
310
- width: 8px;
311
- height: 8px;
312
- border-radius: 50%;
313
- background: var(--secondary);
314
- animation: pulse 2s infinite;
315
- }
316
-
317
- @keyframes pulse {
318
- 0% { opacity: 1; }
319
- 50% { opacity: 0.5; }
320
- 100% { opacity: 1; }
321
- }
322
-
323
- .module-actions {
324
- display: flex;
325
- gap: 0.5rem;
326
- }
327
-
328
- .icon-btn {
329
- background: rgba(255, 255, 255, 0.1);
330
- border: none;
331
- color: var(--light);
332
- width: 32px;
333
- height: 32px;
334
- border-radius: 6px;
335
- cursor: pointer;
336
- display: grid;
337
- place-items: center;
338
- transition: var(--transition);
339
- }
340
-
341
- .icon-btn:hover {
342
- background: var(--primary);
343
- transform: scale(1.1);
344
- }
345
-
346
- .module-content {
347
- padding: 1.5rem;
348
- }
349
-
350
- .code-editor {
351
- background: rgba(0, 0, 0, 0.3);
352
- border: 1px solid rgba(255, 255, 255, 0.1);
353
- border-radius: 8px;
354
- padding: 1rem;
355
- font-family: 'Fira Code', 'Courier New', monospace;
356
- font-size: 0.875rem;
357
- min-height: 200px;
358
- max-height: 400px;
359
- overflow-y: auto;
360
- position: relative;
361
- white-space: pre-wrap;
362
- word-wrap: break-word;
363
- }
364
-
365
- .code-editor:focus {
366
- outline: 2px solid var(--primary);
367
- outline-offset: 2px;
368
- }
369
-
370
- .copy-indicator {
371
- position: absolute;
372
- top: 0.5rem;
373
- right: 0.5rem;
374
- background: var(--secondary);
375
- color: white;
376
- padding: 0.25rem 0.75rem;
377
- border-radius: 4px;
378
- font-size: 0.75rem;
379
- opacity: 0;
380
- transition: opacity 0.3s;
381
- pointer-events: none;
382
- }
383
-
384
- .copy-indicator.show {
385
- opacity: 1;
386
- }
387
-
388
- /* ===== AUTO-SUGGESTION ===== */
389
- .suggestion-dropdown {
390
- position: absolute;
391
- background: var(--darker);
392
- border: 1px solid rgba(255, 255, 255, 0.1);
393
- border-radius: 8px;
394
- max-height: 200px;
395
- overflow-y: auto;
396
- z-index: 50;
397
- display: none;
398
- box-shadow: var(--shadow-xl);
399
- width: 100%;
400
- top: 100%;
401
- left: 0;
402
- margin-top: 0.5rem;
403
- }
404
-
405
- .suggestion-item {
406
- padding: 0.75rem 1rem;
407
- cursor: pointer;
408
- transition: background 0.2s;
409
- display: flex;
410
- justify-content: space-between;
411
- align-items: center;
412
- }
413
-
414
- .suggestion-item:hover {
415
- background: rgba(99, 102, 241, 0.1);
416
- }
417
-
418
- .suggestion-item .history-icon {
419
- color: var(--warning);
420
- font-size: 0.75rem;
421
- }
422
-
423
- /* ===== ARCHIVE ===== */
424
- .archive-list {
425
- display: grid;
426
- gap: 1rem;
427
- margin-top: 2rem;
428
- }
429
-
430
- .archive-item {
431
- background: rgba(255, 255, 255, 0.05);
432
- border: 1px solid rgba(255, 255, 255, 0.1);
433
- border-radius: 8px;
434
- padding: 1.5rem;
435
- display: flex;
436
- justify-content: space-between;
437
- align-items: center;
438
- transition: var(--transition);
439
- }
440
-
441
- .archive-item:hover {
442
- background: rgba(255, 255, 255, 0.08);
443
- transform: translateX(4px);
444
- }
445
-
446
- .archive-info h4 {
447
- margin-bottom: 0.25rem;
448
- }
449
-
450
- .archive-meta {
451
- color: var(--gray);
452
- font-size: 0.875rem;
453
- }
454
-
455
- .search-box {
456
- width: 100%;
457
- max-width: 400px;
458
- background: rgba(255, 255, 255, 0.05);
459
- border: 1px solid rgba(255, 255, 255, 0.1);
460
- border-radius: 8px;
461
- padding: 0.75rem 1rem;
462
- color: var(--light);
463
- font-size: 1rem;
464
- transition: var(--transition);
465
- position: relative;
466
- }
467
-
468
- .search-box:focus {
469
- outline: none;
470
- border-color: var(--primary);
471
- box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
472
- }
473
-
474
- .search-container {
475
- position: relative;
476
- max-width: 400px;
477
- }
478
-
479
- /* ===== SETTINGS ===== */
480
- .settings-grid {
481
- display: grid;
482
- gap: 2rem;
483
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
484
- margin-top: 2rem;
485
- }
486
-
487
- .setting-card {
488
- background: rgba(255, 255, 255, 0.05);
489
- border: 1px solid rgba(255, 255, 255, 0.1);
490
- border-radius: var(--border-radius);
491
- padding: 1.5rem;
492
- }
493
-
494
- .setting-title {
495
- font-size: 1.125rem;
496
- font-weight: 700;
497
- margin-bottom: 1rem;
498
- display: flex;
499
- align-items: center;
500
- gap: 0.5rem;
501
- }
502
-
503
- .toggle-switch {
504
- position: relative;
505
- width: 50px;
506
- height: 24px;
507
- background: rgba(255, 255, 255, 0.2);
508
- border-radius: 12px;
509
- cursor: pointer;
510
- transition: background 0.3s;
511
- }
512
-
513
- .toggle-switch.active {
514
- background: var(--primary);
515
- }
516
-
517
- .toggle-slider {
518
- position: absolute;
519
- top: 2px;
520
- left: 2px;
521
- width: 20px;
522
- height: 20px;
523
- background: white;
524
- border-radius: 50%;
525
- transition: transform 0.3s;
526
- box-shadow: var(--shadow-sm);
527
- }
528
-
529
- .toggle-switch.active .toggle-slider {
530
- transform: translateX(26px);
531
- }
532
-
533
- .setting-row {
534
- display: flex;
535
- justify-content: space-between;
536
- align-items: center;
537
- padding: 0.75rem 0;
538
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
539
- }
540
-
541
- .setting-row:last-child {
542
- border-bottom: none;
543
- }
544
-
545
- /* ===== PROGRESS BAR ===== */
546
- .progress-bar {
547
- position: fixed;
548
- top: 0;
549
- left: 0;
550
- width: 100%;
551
- height: 3px;
552
- background: var(--primary);
553
- transform: scaleX(0);
554
- transform-origin: left;
555
- transition: transform 0.3s;
556
- z-index: 200;
557
- }
558
-
559
- .progress-bar.active {
560
- transform: scaleX(1);
561
- }
562
-
563
- /* ===== NOTIFICATIONS ===== */
564
- .notification {
565
- position: fixed;
566
- bottom: 2rem;
567
- right: 2rem;
568
- background: var(--darker);
569
- border: 1px solid rgba(255, 255, 255, 0.1);
570
- border-radius: 8px;
571
- padding: 1rem 1.5rem;
572
- box-shadow: var(--shadow-xl);
573
- transform: translateY(100px);
574
- opacity: 0;
575
- transition: var(--transition);
576
- z-index: 150;
577
- max-width: 400px;
578
- }
579
-
580
- .notification.show {
581
- transform: translateY(0);
582
- opacity: 1;
583
- }
584
-
585
- .notification.success {
586
- border-left: 4px solid var(--secondary);
587
- }
588
-
589
- .notification.error {
590
- border-left: 4px solid var(--danger);
591
- }
592
-
593
- .notification.info {
594
- border-left: 4px solid var(--primary);
595
- }
596
-
597
- /* ===== LOADING SPINNER ===== */
598
- .spinner {
599
- width: 40px;
600
- height: 40px;
601
- border: 3px solid rgba(255, 255, 255, 0.1);
602
- border-top-color: var(--primary);
603
- border-radius: 50%;
604
- animation: spin 1s linear infinite;
605
- margin: 2rem auto;
606
- }
607
-
608
- @keyframes spin {
609
- to { transform: rotate(360deg); }
610
- }
611
-
612
- /* ===== RESPONSIVE ===== */
613
- @media (max-width: 768px) {
614
- .header {
615
- padding: 1rem;
616
- }
617
-
618
- .main-content {
619
- padding: 1rem;
620
- }
621
-
622
- .module-grid {
623
- grid-template-columns: 1fr;
624
- }
625
-
626
- .action-buttons {
627
- flex-direction: column;
628
- }
629
-
630
- .btn {
631
- width: 100%;
632
- justify-content: center;
633
- }
634
- }
635
-
636
- /* ===== UTILITY CLASSES ===== */
637
- .hidden {
638
- display: none !important;
639
- }
640
-
641
- .fade-in {
642
- animation: fadeIn 0.3s ease-in-out;
643
- }
644
-
645
- .text-muted {
646
- color: var(--gray);
647
- }
648
-
649
- .mb-2 { margin-bottom: 0.5rem; }
650
- .mb-4 { margin-bottom: 1rem; }
651
- .mt-4 { margin-top: 1rem; }
652
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
653
  </head>
 
654
  <body>
655
- <div class="progress-bar" id="progressBar"></div>
656
-
657
- <header class="header">
658
- <div class="logo-section">
659
- <div class="logo">CF</div>
660
- <div class="brand">CodeFlow Pro</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
661
  </div>
662
- <nav class="nav-tabs">
663
- <button class="tab-btn active" data-tab="files">
664
- <i class="fas fa-folder-open"></i> Dateien
665
- <span class="badge" id="fileCount">0</span>
666
- </button>
667
- <button class="tab-btn" data-tab="modules">
668
- <i class="fas fa-puzzle-piece"></i> Module
669
- <span class="badge" id="moduleCount">0</span>
670
- </button>
671
- <button class="tab-btn" data-tab="archive">
672
- <i class="fas fa-archive"></i> Archiv
673
- <span class="badge" id="archiveCount">0</span>
674
- </button>
675
- <button class="tab-btn" data-tab="settings">
676
- <i class="fas fa-cog"></i> Einstellungen
677
- </button>
678
- </nav>
679
- <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">
680
- Built with anycoder
681
- </a>
682
- </header>
683
-
684
- <main class="main-content">
685
- <!-- FILES TAB -->
686
- <div class="tab-panel active" id="files-tab">
687
- <h2 class="mb-4">Dateien & Ordner verarbeiten</h2>
688
-
689
- <div class="upload-zone" id="uploadZone">
690
- <div class="upload-icon">
691
- <i class="fas fa-cloud-upload-alt"></i>
692
- </div>
693
- <div class="upload-text">Dateien oder Ordner hier ablegen</div>
694
- <div class="upload-hint">Unterstützt: HTML, JS, CSS, TXT</div>
695
- <input type="file" id="fileInput" class="file-input" multiple webkitdirectory directory>
696
- </div>
697
-
698
- <div class="action-buttons">
699
- <button class="btn" id="selectFilesBtn">
700
- <i class="fas fa-file"></i> Dateien auswählen
701
- </button>
702
- <button class="btn" id="selectFolderBtn">
703
- <i class="fas fa-folder"></i> Ordner auswählen
704
- </button>
705
- <button class="btn btn-secondary" id="processBtn" disabled>
706
- <i class="fas fa-cogs"></i> Verarbeiten
707
- </button>
708
- <button class="btn btn-danger" id="clearBtn">
709
- <i class="fas fa-trash"></i> Alle löschen
710
- </button>
711
- </div>
712
-
713
- <div id="fileList" class="mt-4"></div>
714
  </div>
715
-
716
- <!-- MODULES TAB -->
717
- <div class="tab-panel" id="modules-tab">
718
- <h2 class="mb-4">Module verwalten</h2>
719
-
720
- <div class="search-container">
721
- <input type="text" class="search-box" id="moduleSearch" placeholder="Module suchen...">
722
- <div class="suggestion-dropdown" id="moduleSuggestions"></div>
723
- </div>
724
-
725
- <div class="action-buttons">
726
- <button class="btn" id="minifyAllBtn">
727
- <i class="fas fa-compress"></i> Alle minifizieren
728
- </button>
729
- <button class="btn btn-secondary" id="exportAllBtn">
730
- <i class="fas fa-download"></i> Alle exportieren
731
- </button>
732
- <button class="btn btn-danger" id="removeDuplicatesBtn">
733
- <i class="fas fa-clone"></i> Duplikate entfernen
734
- </button>
735
- </div>
736
-
737
- <div class="module-grid" id="moduleGrid"></div>
738
  </div>
739
-
740
- <!-- ARCHIVE TAB -->
741
- <div class="tab-panel" id="archive-tab">
742
- <h2 class="mb-4">Archivierte Projekte</h2>
743
-
744
- <div class="search-container">
745
- <input type="text" class="search-box" id="archiveSearch" placeholder="Archiv durchsuchen...">
746
- </div>
747
-
748
- <div class="action-buttons">
749
- <button class="btn" id="exportArchiveBtn">
750
- <i class="fas fa-file-archive"></i> Archiv exportieren
751
- </button>
752
- <button class="btn btn-danger" id="clearArchiveBtn">
753
- <i class="fas fa-broom"></i> Archiv leeren
754
- </button>
755
- </div>
756
-
757
- <div class="archive-list" id="archiveList"></div>
758
  </div>
759
-
760
- <!-- SETTINGS TAB -->
761
- <div class="tab-panel" id="settings-tab">
762
- <h2 class="mb-4">Einstellungen</h2>
763
-
764
- <div class="settings-grid">
765
- <div class="setting-card">
766
- <h3 class="setting-title">
767
- <i class="fas fa-magic"></i> Automatisierung
768
- </h3>
769
- <div class="setting-row">
770
- <span>Auto-Speicherung</span>
771
- <div class="toggle-switch active" data-setting="autoSave"></div>
772
- </div>
773
- <div class="setting-row">
774
- <span>Auto-Benennung</span>
775
- <div class="toggle-switch active" data-setting="autoNaming"></div>
776
- </div>
777
- <div class="setting-row">
778
- <span>Duplikat-Prüfung</span>
779
- <div class="toggle-switch active" data-setting="duplicateCheck"></div>
780
- </div>
781
- </div>
782
-
783
- <div class="setting-card">
784
- <h3 class="setting-title">
785
- <i class="fas fa-code"></i> Code-Verarbeitung
786
- </h3>
787
- <div class="setting-row">
788
- <span>HTML-Tags entfernen</span>
789
- <div class="toggle-switch active" data-setting="removeHtmlTags"></div>
790
- </div>
791
- <div class="setting-row">
792
- <span>Minifizierung</span>
793
- <div class="toggle-switch" data-setting="minify"></div>
794
- </div>
795
- <div class="setting-row">
796
- <span>Modernes Format</span>
797
- <div class="toggle-switch active" data-setting="modernFormat"></div>
798
- </div>
799
- </div>
800
-
801
- <div class="setting-card">
802
- <h3 class="setting-title">
803
- <i class="fas fa-history"></i> Historie
804
- </h3>
805
- <div class="setting-row">
806
- <span>Such-Historie speichern</span>
807
- <div class="toggle-switch active" data-setting="searchHistory"></div>
808
- </div>
809
- <div class="setting-row">
810
- <span>Letzte Sitzung wiederherstellen</span>
811
- <div class="toggle-switch active" data-setting="restoreSession"></div>
812
- </div>
813
- <div class="setting-row">
814
- <button class="btn" id="clearHistoryBtn" style="width: 100%;">
815
- <i class="fas fa-eraser"></i> Historie leeren
816
- </button>
817
- </div>
818
- </div>
819
- </div>
 
 
820
  </div>
821
- </main>
822
-
823
- <div class="notification" id="notification"></div>
824
-
825
- <script>
826
- // ===== MODERN JAVASCRIPT ES2022+ =====
827
- class CodeFlowApp {
828
- #files = new Map();
829
- #modules = new Map();
830
- #archive = new Map();
831
- #settings = new Map([
832
- ['autoSave', true],
833
- ['autoNaming', true],
834
- ['duplicateCheck', true],
835
- ['removeHtmlTags', true],
836
- ['minify', false],
837
- ['modernFormat', true],
838
- ['searchHistory', true],
839
- ['restoreSession', true]
840
- ]);
841
- #history = {
842
- searches: [],
843
- processedFiles: []
844
- };
845
- #suggestions = new Set();
846
-
847
- constructor() {
848
- this.#init();
849
- this.#loadFromStorage();
850
- this.#setupEventListeners();
851
- this.#setupAutoSave();
852
- this.#setupLazyLoad();
853
- }
854
-
855
- // ===== INITIALIZATION =====
856
- #init() {
857
- console.log('🚀 CodeFlow Pro initialisiert');
858
- this.#updateBadgeCounts();
859
- this.#renderArchive();
860
- this.#setupServiceWorker();
861
- }
862
-
863
- // ===== STORAGE MANAGEMENT =====
864
- #saveToStorage() {
865
- if (!this.#settings.get('autoSave')) return;
866
-
867
- const data = {
868
- modules: Array.from(this.#modules.entries()),
869
- archive: Array.from(this.#archive.entries()),
870
- settings: Array.from(this.#settings.entries()),
871
- history: this.#history,
872
- timestamp: Date.now()
873
- };
874
-
875
- localStorage.setItem('codeflow-data', JSON.stringify(data));
876
- this.#showNotification('Auto-gespeichert', 'info');
877
- }
878
-
879
- #loadFromStorage() {
880
- if (!this.#settings.get('restoreSession')) return;
881
-
882
- const saved = localStorage.getItem('codeflow-data');
883
- if (!saved) return;
884
-
885
- try {
886
- const data = JSON.parse(saved);
887
- this.#modules = new Map(data.modules || []);
888
- this.#archive = new Map(data.archive || []);
889
- this.#settings = new Map(data.settings || this.#settings);
890
- this.#history = data.history || this.#history;
891
-
892
- this.#updateBadgeCounts();
893
- this.#renderArchive();
894
- this.#applySettings();
895
-
896
- console.log('📦 Daten aus Speicher geladen');
897
- } catch (e) {
898
- console.error('Fehler beim Laden:', e);
899
- }
900
- }
901
-
902
- // ===== EVENT LISTENERS =====
903
- #setupEventListeners() {
904
- // Tabs
905
- document.querySelectorAll('.tab-btn').forEach(btn => {
906
- btn.addEventListener('click', (e) => this.#switchTab(e.target.dataset.tab));
907
- });
908
-
909
- // Upload Zone
910
- const zone = document.getElementById('uploadZone');
911
- zone.addEventListener('click', () => document.getElementById('fileInput').click());
912
- zone.addEventListener('dragover', this.#handleDragOver.bind(this));
913
- zone.addEventListener('dragleave', this.#handleDragLeave.bind(this));
914
- zone.addEventListener('drop', this.#handleDrop.bind(this));
915
-
916
- // File Input
917
- document.getElementById('fileInput').addEventListener('change', this.#handleFileSelect.bind(this));
918
- document.getElementById('selectFilesBtn').addEventListener('click', () => {
919
- document.getElementById('fileInput').removeAttribute('webkitdirectory');
920
- document.getElementById('fileInput').click();
921
- });
922
- document.getElementById('selectFolderBtn').addEventListener('click', () => {
923
- document.getElementById('fileInput').setAttribute('webkitdirectory', '');
924
- document.getElementById('fileInput').click();
925
- });
926
-
927
- // Action Buttons
928
- document.getElementById('processBtn').addEventListener('click', () => this.#processFiles());
929
- document.getElementById('clearBtn').addEventListener('click', () => this.#clearFiles());
930
- document.getElementById('minifyAllBtn').addEventListener('click', () => this.#minifyAll());
931
- document.getElementById('exportAllBtn').addEventListener('click', () => this.#exportAll());
932
- document.getElementById('removeDuplicatesBtn').addEventListener('click', () => this.#removeDuplicates());
933
- document.getElementById('clearArchiveBtn').addEventListener('click', () => this.#clearArchive());
934
- document.getElementById('exportArchiveBtn').addEventListener('click', () => this.#exportArchive());
935
- document.getElementById('clearHistoryBtn').addEventListener('click', () => this.#clearHistory());
936
-
937
- // Search
938
- document.getElementById('moduleSearch').addEventListener('input', (e) => this.#handleSearch(e.target.value));
939
-
940
- // Settings
941
- document.querySelectorAll('.toggle-switch').forEach(toggle => {
942
- toggle.addEventListener('click', (e) => this.#toggleSetting(e.target.dataset.setting));
943
- });
944
-
945
- // Auto-save on input
946
- document.addEventListener('input', () => this.#debouncedSave());
947
- }
948
-
949
- // ===== FILE HANDLING =====
950
- async #handleFileSelect(e) {
951
- const files = Array.from(e.target.files);
952
- await this.#addFiles(files);
953
- }
954
-
955
- #handleDragOver(e) {
956
- e.preventDefault();
957
- e.currentTarget.classList.add('dragover');
958
- }
959
-
960
- #handleDragLeave(e) {
961
- e.currentTarget.classList.remove('dragover');
962
- }
963
-
964
- async #handleDrop(e) {
965
- e.preventDefault();
966
- e.currentTarget.classList.remove('dragover');
967
-
968
- const items = Array.from(e.dataTransfer.items);
969
- const files = [];
970
-
971
- for (const item of items) {
972
- if (item.kind === 'file') {
973
- const file = item.getAsFile();
974
- if (item.webkitGetAsEntry) {
975
- const entry = item.webkitGetAsEntry();
976
- if (entry.isDirectory) {
977
- await this.#readDirectory(entry, files);
978
- } else {
979
- files.push(file);
980
- }
981
- } else {
982
- files.push(file);
983
- }
984
- }
985
- }
986
-
987
- await this.#addFiles(files);
988
- }
989
-
990
- async #readDirectory(entry, files) {
991
- const reader = entry.createReader();
992
- const entries = await new Promise(resolve => reader.readEntries(resolve));
993
-
994
- for (const subEntry of entries) {
995
- if (subEntry.isDirectory) {
996
- await this.#readDirectory(subEntry, files);
997
- } else {
998
- const file = await new Promise(resolve => subEntry.file(resolve));
999
- files.push(file);
1000
- }
1001
- }
1002
- }
1003
-
1004
- async #addFiles(files) {
1005
- const validTypes = ['text/html', 'text/css', 'text/javascript', 'application/javascript', 'text/plain'];
1006
-
1007
- for (const file of files) {
1008
- if (validTypes.includes(file.type) || file.name.match(/\.(html|js|css|txt)$/i)) {
1009
- this.#files.set(file.name, {
1010
- file,
1011
- id: crypto.randomUUID(),
1012
- processed: false,
1013
- timestamp: Date.now()
1014
- });
1015
- }
1016
- }
1017
-
1018
- this.#renderFileList();
1019
- this.#updateBadgeCounts();
1020
- this.#showNotification(`${files.length} Dateien hinzugefügt`, 'success');
1021
-
1022
- if (this.#settings.get('autoSave')) {
1023
- this.#debouncedSave();
1024
- }
1025
- }
1026
-
1027
- #renderFileList() {
1028
- const container = document.getElementById('fileList');
1029
- if (this.#files.size === 0) {
1030
- container.innerHTML = '<p class="text-muted">Keine Dateien ausgewählt</p>';
1031
- document.getElementById('processBtn').disabled = true;
1032
- return;
1033
- }
1034
-
1035
- container.innerHTML = Array.from(this.#files.values()).map(fileObj => `
1036
- <div class="archive-item fade-in">
1037
- <div class="archive-info">
1038
- <h4>${fileObj.file.name}</h4>
1039
- <div class="archive-meta">
1040
- ${this.#formatBytes(fileObj.file.size)} • ${new Date(fileObj.timestamp).toLocaleString()}
1041
- </div>
1042
- </div>
1043
- <button class="icon-btn" onclick="app.#removeFile('${fileObj.id}')">
1044
- <i class="fas fa-times"></i>
1045
- </button>
1046
- </div>
1047
- `).join('');
1048
-
1049
- document.getElementById('processBtn').disabled = false;
1050
- }
1051
-
1052
- #removeFile(id) {
1053
- const entry = Array.from(this.#files.entries()).find(([, v]) => v.id === id);
1054
- if (entry) {
1055
- this.#files.delete(entry[0]);
1056
- this.#renderFileList();
1057
- this.#updateBadgeCounts();
1058
- }
1059
- }
1060
-
1061
- #clearFiles() {
1062
- this.#files.clear();
1063
- this.#renderFileList();
1064
- this.#updateBadgeCounts();
1065
- this.#showNotification('Alle Dateien entfernt', 'info');
1066
- }
1067
-
1068
- // ===== FILE PROCESSING =====
1069
- async #processFiles() {
1070
- if (this.#files.size === 0) return;
1071
-
1072
- this.#showProgress(true);
1073
-
1074
- for (const [name, fileObj] of this.#files) {
1075
- try {
1076
- const content = await fileObj.file.text();
1077
- const processed = this.#processContent(content, name);
1078
- const moduleId = crypto.randomUUID();
1079
-
1080
- this.#modules.set(moduleId, {
1081
- name: this.#autoName(name),
1082
- content: processed,
1083
- original: content,
1084
- timestamp: Date.now(),
1085
- fileName: name
1086
- });
1087
-
1088
- fileObj.processed = true;
1089
- } catch (e) {
1090
- console.error(`Fehler bei ${name}:`, e);
1091
- this.#showNotification(`Fehler bei ${name}`, 'error');
1092
- }
1093
- }
1094
-
1095
- if (this.#settings.get('duplicateCheck')) {
1096
- this.#removeDuplicates();
1097
- }
1098
-
1099
- this.#renderModules();
1100
- this.#updateBadgeCounts();
1101
- this.#saveToArchive();
1102
- this.#showProgress(false);
1103
- this.#showNotification('Verarbeitung abgeschlossen', 'success');
1104
- this.#switchTab('modules');
1105
- }
1106
-
1107
- #processContent(content, fileName) {
1108
- let processed = content;
1109
-
1110
- // Remove basic HTML tags
1111
- if (this.#settings.get('removeHtmlTags')) {
1112
- processed = processed
1113
- .replace(/<!DOCTYPE[^>]*>/gi, '')
1114
- .replace(/<html[^>]*>/gi, '')
1115
- .replace(/<\/html>/gi, '')
1116
- .replace(/<head[^>]*>[\s\S]*?<\/head>/gi, '')
1117
- .replace(/<body[^>]*>/gi, '')
1118
- .replace(/<\/body>/gi, '')
1119
- .replace(/<meta[^>]*>/gi, '')
1120
- .replace(/<title[^>]*>[\s\S]*?<\/title>/gi, '');
1121
- }
1122
-
1123
- // Split into modules for HTML files
1124
- if (fileName.endsWith('.html')) {
1125
- processed = this.#splitHtmlIntoModules(processed);
1126
- }
1127
-
1128
- // Minify if enabled
1129
- if (this.#settings.get('minify')) {
1130
- processed = this.#minifyCode(processed);
1131
- }
1132
-
1133
- // Modern format
1134
- if (this.#settings.get('modernFormat')) {
1135
- processed = this.#modernizeCode(processed);
1136
- }
1137
-
1138
- return processed;
1139
- }
1140
-
1141
- #splitHtmlIntoModules(html) {
1142
- const modules = [];
1143
- const regex = /<([a-zA-Z0-9-]+)[^>]*>[\s\S]*?<\/\1>/g;
1144
- let match;
1145
-
1146
- while ((match = regex.exec(html)) !== null) {
1147
- modules.push({
1148
- tag: match[1],
1149
- content: match[0].trim()
1150
- });
1151
- }
1152
-
1153
- return modules.length > 0
1154
- ? modules.map((m, i) => `// Module ${i + 1}: <${m.tag}>\n${m.content}`).join('\n\n')
1155
- : html;
1156
- }
1157
-
1158
- #minifyCode(code) {
1159
- return code
1160
- .replace(/\s+/g, ' ')
1161
- .replace(/;\s*}/g, '}')
1162
- .replace(/{/g, '{')
1163
- .replace(/}/g, '}')
1164
- .trim();
1165
- }
1166
-
1167
- #modernizeCode(code) {
1168
- // Convert var to let/const
1169
- code = code.replace(/\bvar\b/g, 'let');
1170
-
1171
- // Convert function expressions to arrow functions
1172
- code = code.replace(/function\s*\(([^)]*)\)\s*{/g, '($1) => {');
1173
-
1174
- // Convert .then() to async/await (simple cases)
1175
- code = code.replace(/\.then\(([^)]+)\)/g, 'await $1');
1176
-
1177
- return code;
1178
- }
1179
-
1180
- #autoName(originalName) {
1181
- if (!this.#settings.get('autoNaming')) return originalName;
1182
-
1183
- const timestamp = Date.now().toString(36);
1184
- const random = Math.random().toString(36).substr(2, 4);
1185
- return `module_${timestamp}_${random}_${originalName}`;
1186
- }
1187
-
1188
- // ===== MODULE MANAGEMENT =====
1189
- #renderModules(searchTerm = '') {
1190
- const container = document.getElementById('moduleGrid');
1191
- const modules = Array.from(this.#modules.entries())
1192
- .filter(([, m]) => !searchTerm || m.name.toLowerCase().includes(searchTerm.toLowerCase()));
1193
-
1194
- if (modules.length === 0) {
1195
- container.innerHTML = '<p class="text-muted">Keine Module vorhanden</p>';
1196
- return;
1197
- }
1198
-
1199
- container.innerHTML = modules.map(([id, module]) => `
1200
- <div class="module-card fade-in">
1201
- <div class="module-header">
1202
- <div class="module-title">
1203
- <div class="module-status"></div>
1204
- ${module.name}
1205
- </div>
1206
- <div class="module-actions">
1207
- <button class="icon-btn" onclick="app.#copyToClipboard('${id}')" title="Kopieren">
1208
- <i class="fas fa-copy"></i>
1209
- </button>
1210
- <button class="icon-btn" onclick="app.#pasteToModule('${id}')" title="Einfügen">
1211
- <i class="fas fa-paste"></i>
1212
- </button>
1213
- <button class="icon-btn" onclick="app.#exportModule('${id}')" title="Exportieren">
1214
- <i class="fas fa-download"></i>
1215
- </button>
1216
- <button class="icon-btn" onclick="app.#removeModule('${id}')" title="Löschen">
1217
- <i class="fas fa-trash"></i>
1218
- </button>
1219
- </div>
1220
- </div>
1221
- <div class="module-content">
1222
- <div class="code-editor" contenteditable="true" data-module-id="${id}">
1223
- ${this.#escapeHtml(module.content)}
1224
- <div class="copy-indicator" id="indicator-${id}">Kopiert!</div>
1225
- </div>
1226
- </div>
1227
- </div>
1228
- `).join('');
1229
-
1230
- this.#setupModuleEditing();
1231
- }
1232
-
1233
- #setupModuleEditing() {
1234
- document.querySelectorAll('.code-editor').forEach(editor => {
1235
- editor.addEventListener('input', (e) => {
1236
- const id = e.target.dataset.moduleId;
1237
- const module = this.#modules.get(id);
1238
- if (module) {
1239
- module.content = e.target.textContent;
1240
- this.#debouncedSave();
1241
- }
1242
- });
1243
-
1244
- // Auto-suggestion
1245
- editor.addEventListener('keydown', (e) => {
1246
- if (e.key === 'Tab') {
1247
- e.preventDefault();
1248
- this.#insertSuggestion(e.target);
1249
- }
1250
- });
1251
- });
1252
- }
1253
 
1254
- #insertSuggestion(editor) {
1255
- const suggestions = ['function', 'const', 'let', 'async', 'await', 'return'];
1256
- const random = suggestions[Math.floor(Math.random() * suggestions.length)];
1257
- document.execCommand('insertText', false, random);
1258
- }
 
 
 
 
 
 
 
 
 
 
 
 
1259
 
1260
- async #copyToClipboard(id) {
1261
- const module = this.#modules.get(id);
1262
- if (!module) return;
1263
-
1264
- try {
1265
- await navigator.clipboard.writeText(module.content);
1266
- this.#showCopyIndicator(id);
1267
- this.#showNotification('In Zwischenablage kopiert', 'success');
1268
- } catch (e) {
1269
- console.error('Kopieren fehlgeschlagen:', e);
1270
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1271
  }
1272
-
1273
- #showCopyIndicator(id) {
1274
- const indicator = document.getElementBy
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <!DOCTYPE html>
2
  <html lang="de">
3
  <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>CodeFlow Pro - CSS Playground & Archiv</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
8
+ <style>
9
+ /* ===== MODERN CSS RESET & BASE ===== */
10
+ *, *::before, *::after {
11
+ box-sizing: border-box;
12
+ margin: 0;
13
+ padding: 0;
14
+ }
15
+
16
+ :root {
17
+ --primary: #6366f1;
18
+ --primary-dark: #4f46e5;
19
+ --secondary: #10b981;
20
+ --danger: #ef4444;
21
+ --warning: #f59e0b;
22
+ --dark: #1f2937;
23
+ --darker: #111827;
24
+ --light: #f9fafb;
25
+ --gray: #9ca3af;
26
+ --border-radius: 12px;
27
+ --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
28
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
29
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
30
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
31
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
32
+ }
33
+
34
+ html { scroll-behavior: smooth; }
35
+
36
+ body {
37
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
38
+ background: linear-gradient(135deg, var(--darker) 0%, var(--dark) 100%);
39
+ color: var(--light);
40
+ min-height: 100vh;
41
+ display: grid;
42
+ grid-template-rows: auto 1fr;
43
+ line-height: 1.6;
44
+ }
45
+
46
+ /* ===== HEADER ===== */
47
+ .header {
48
+ background: rgba(31, 41, 55, 0.95);
49
+ backdrop-filter: blur(10px);
50
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
51
+ padding: 1rem 2rem;
52
+ position: sticky;
53
+ top: 0;
54
+ z-index: 100;
55
+ display: flex;
56
+ justify-content: space-between;
57
+ align-items: center;
58
+ flex-wrap: wrap;
59
+ gap: 1rem;
60
+ }
61
+
62
+ .logo-section {
63
+ display: flex;
64
+ align-items: center;
65
+ gap: 0.75rem;
66
+ }
67
+
68
+ .logo {
69
+ width: 40px;
70
+ height: 40px;
71
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
72
+ border-radius: 10px;
73
+ display: grid;
74
+ place-items: center;
75
+ font-weight: bold;
76
+ font-size: 1.25rem;
77
+ }
78
+
79
+ .brand {
80
+ font-size: 1.5rem;
81
+ font-weight: 700;
82
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
83
+ -webkit-background-clip: text;
84
+ -webkit-text-fill-color: transparent;
85
+ }
86
+
87
+ .anycoder-link {
88
+ background: var(--primary);
89
+ color: white;
90
+ padding: 0.5rem 1rem;
91
+ border-radius: 20px;
92
+ text-decoration: none;
93
+ font-size: 0.875rem;
94
+ font-weight: 600;
95
+ transition: var(--transition);
96
+ box-shadow: var(--shadow-md);
97
+ }
98
+
99
+ .anycoder-link:hover {
100
+ background: var(--primary-dark);
101
+ transform: translateY(-2px);
102
+ box-shadow: var(--shadow-lg);
103
+ }
104
+
105
+ /* ===== NAVIGATION TABS ===== */
106
+ .nav-tabs {
107
+ display: flex;
108
+ gap: 0.5rem;
109
+ overflow-x: auto;
110
+ scrollbar-width: none;
111
+ }
112
+
113
+ .nav-tabs::-webkit-scrollbar { display: none; }
114
+
115
+ .tab-btn {
116
+ background: rgba(255, 255, 255, 0.05);
117
+ border: 1px solid rgba(255, 255, 255, 0.1);
118
+ color: var(--gray);
119
+ padding: 0.75rem 1.5rem;
120
+ border-radius: 8px;
121
+ cursor: pointer;
122
+ font-weight: 600;
123
+ transition: var(--transition);
124
+ white-space: nowrap;
125
+ display: flex;
126
+ align-items: center;
127
+ gap: 0.5rem;
128
+ }
129
+
130
+ .tab-btn:hover {
131
+ background: rgba(255, 255, 255, 0.1);
132
+ color: var(--light);
133
+ }
134
+
135
+ .tab-btn.active {
136
+ background: var(--primary);
137
+ color: white;
138
+ border-color: var(--primary);
139
+ box-shadow: var(--shadow-md);
140
+ }
141
+
142
+ .tab-btn .badge {
143
+ background: var(--danger);
144
+ color: white;
145
+ padding: 0.125rem 0.5rem;
146
+ border-radius: 10px;
147
+ font-size: 0.75rem;
148
+ font-weight: 700;
149
+ }
150
+
151
+ /* ===== MAIN CONTENT ===== */
152
+ .main-content {
153
+ padding: 2rem;
154
+ container-type: inline-size;
155
+ overflow-y: auto;
156
+ }
157
+
158
+ .tab-panel {
159
+ display: none;
160
+ animation: fadeIn 0.3s ease-in-out;
161
+ }
162
+
163
+ .tab-panel.active { display: block; }
164
+
165
+ @keyframes fadeIn {
166
+ from { opacity: 0; transform: translateY(10px); }
167
+ to { opacity: 1; transform: translateY(0); }
168
+ }
169
+
170
+ /* ===== UPLOAD SECTION ===== */
171
+ .upload-zone {
172
+ background: rgba(255, 255, 255, 0.03);
173
+ border: 2px dashed rgba(255, 255, 255, 0.2);
174
+ border-radius: var(--border-radius);
175
+ padding: 3rem;
176
+ text-align: center;
177
+ transition: var(--transition);
178
+ cursor: pointer;
179
+ position: relative;
180
+ overflow: hidden;
181
+ }
182
+
183
+ .upload-zone:hover {
184
+ border-color: var(--primary);
185
+ background: rgba(99, 102, 241, 0.05);
186
+ }
187
+
188
+ .upload-zone.dragover {
189
+ border-color: var(--secondary);
190
+ background: rgba(16, 185, 129, 0.1);
191
+ transform: scale(1.02);
192
+ }
193
+
194
+ .upload-icon {
195
+ font-size: 3rem;
196
+ color: var(--gray);
197
+ margin-bottom: 1rem;
198
+ }
199
+
200
+ .upload-text {
201
+ font-size: 1.25rem;
202
+ margin-bottom: 0.5rem;
203
+ }
204
+
205
+ .upload-hint {
206
+ color: var(--gray);
207
+ font-size: 0.875rem;
208
+ }
209
+
210
+ .file-input { display: none; }
211
+
212
+ .action-buttons {
213
+ display: flex;
214
+ gap: 1rem;
215
+ margin-top: 2rem;
216
+ flex-wrap: wrap;
217
+ }
218
+
219
+ .btn {
220
+ background: var(--primary);
221
+ color: white;
222
+ border: none;
223
+ padding: 0.75rem 1.5rem;
224
+ border-radius: 8px;
225
+ cursor: pointer;
226
+ font-weight: 600;
227
+ transition: var(--transition);
228
+ display: inline-flex;
229
+ align-items: center;
230
+ gap: 0.5rem;
231
+ box-shadow: var(--shadow-sm);
232
+ }
233
+
234
+ .btn:hover {
235
+ background: var(--primary-dark);
236
+ transform: translateY(-2px);
237
+ box-shadow: var(--shadow-md);
238
+ }
239
+
240
+ .btn-secondary { background: var(--secondary); }
241
+ .btn-secondary:hover { background: #059669; }
242
+ .btn-danger { background: var(--danger); }
243
+ .btn-danger:hover { background: #dc2626; }
244
+ .btn-warning { background: var(--warning); }
245
+ .btn-warning:hover { background: #d97706; }
246
+
247
+ /* ===== MODULE GRID & CSS CARDS ===== */
248
+ .module-grid {
249
+ display: grid;
250
+ gap: 1.5rem;
251
+ grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));
252
+ margin-top: 2rem;
253
+ }
254
+
255
+ @container (max-width: 1000px) {
256
+ .module-grid {
257
+ grid-template-columns: 1fr;
258
+ }
259
+ }
260
+
261
+ .module-card {
262
+ background: rgba(255, 255, 255, 0.05);
263
+ border: 1px solid rgba(255, 255, 255, 0.1);
264
+ border-radius: var(--border-radius);
265
+ overflow: hidden;
266
+ transition: var(--transition);
267
+ position: relative;
268
+ }
269
+
270
+ .module-card:hover {
271
+ transform: translateY(-4px);
272
+ box-shadow: var(--shadow-xl);
273
+ border-color: rgba(99, 102, 241, 0.3);
274
+ }
275
+
276
+ .module-card.selected {
277
+ border-color: var(--secondary);
278
+ background: rgba(16, 185, 129, 0.05);
279
+ }
280
+
281
+ .module-header {
282
+ background: rgba(255, 255, 255, 0.03);
283
+ padding: 1rem 1.5rem;
284
+ display: flex;
285
+ justify-content: space-between;
286
+ align-items: center;
287
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
288
+ gap: 1rem;
289
+ }
290
+
291
+ .module-title {
292
+ font-weight: 700;
293
+ display: flex;
294
+ align-items: center;
295
+ gap: 0.5rem;
296
+ flex: 1;
297
+ }
298
+
299
+ .module-checkbox {
300
+ width: 18px;
301
+ height: 18px;
302
+ cursor: pointer;
303
+ accent-color: var(--secondary);
304
+ }
305
+
306
+ .module-status {
307
+ width: 8px;
308
+ height: 8px;
309
+ border-radius: 50%;
310
+ background: var(--secondary);
311
+ animation: pulse 2s infinite;
312
+ }
313
+
314
+ @keyframes pulse {
315
+ 0%, 100% { opacity: 1; }
316
+ 50% { opacity: 0.5; }
317
+ }
318
+
319
+ .module-actions {
320
+ display: flex;
321
+ gap: 0.5rem;
322
+ }
323
+
324
+ .icon-btn {
325
+ background: rgba(255, 255, 255, 0.1);
326
+ border: none;
327
+ color: var(--light);
328
+ width: 32px;
329
+ height: 32px;
330
+ border-radius: 6px;
331
+ cursor: pointer;
332
+ display: grid;
333
+ place-items: center;
334
+ transition: var(--transition);
335
+ }
336
+
337
+ .icon-btn:hover {
338
+ background: var(--primary);
339
+ transform: scale(1.1);
340
+ }
341
+
342
+ .module-content {
343
+ padding: 1.5rem;
344
+ }
345
+
346
+ .css-preview {
347
+ background: rgba(0, 0, 0, 0.3);
348
+ border: 1px solid rgba(255, 255, 255, 0.1);
349
+ border-radius: 8px;
350
+ padding: 1rem;
351
+ margin-bottom: 1rem;
352
+ min-height: 100px;
353
+ max-height: 250px;
354
+ overflow-y: auto;
355
+ }
356
+
357
+ .css-editor {
358
+ background: rgba(0, 0, 0, 0.3);
359
+ border: 1px solid rgba(255, 255, 255, 0.1);
360
+ border-radius: 8px;
361
+ padding: 1rem;
362
+ font-family: 'Fira Code', 'Courier New', monospace;
363
+ font-size: 0.875rem;
364
+ min-height: 150px;
365
+ max-height: 300px;
366
+ overflow-y: auto;
367
+ position: relative;
368
+ white-space: pre-wrap;
369
+ word-wrap: break-word;
370
+ }
371
+
372
+ .css-editor:focus {
373
+ outline: 2px solid var(--primary);
374
+ outline-offset: 2px;
375
+ }
376
+
377
+ .css-controls {
378
+ display: grid;
379
+ gap: 0.75rem;
380
+ margin-top: 1rem;
381
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
382
+ }
383
+
384
+ .control-group {
385
+ display: flex;
386
+ flex-direction: column;
387
+ gap: 0.25rem;
388
+ }
389
+
390
+ .control-group label {
391
+ font-size: 0.875rem;
392
+ color: var(--gray);
393
+ display: flex;
394
+ justify-content: space-between;
395
+ }
396
+
397
+ .control-group input[type="range"],
398
+ .control-group input[type="text"],
399
+ .control-group input[type="color"],
400
+ .control-group select {
401
+ background: rgba(255, 255, 255, 0.05);
402
+ border: 1px solid rgba(255, 255, 255, 0.1);
403
+ border-radius: 6px;
404
+ padding: 0.5rem;
405
+ color: var(--light);
406
+ transition: var(--transition);
407
+ }
408
+
409
+ .control-group input:focus {
410
+ border-color: var(--primary);
411
+ outline: none;
412
+ }
413
+
414
+ .control-group input[type="range"] {
415
+ padding: 0;
416
+ height: 6px;
417
+ -webkit-appearance: none;
418
+ background: rgba(255, 255, 255, 0.1);
419
+ }
420
+
421
+ .control-group input[type="range"]::-webkit-slider-thumb {
422
+ -webkit-appearance: none;
423
+ width: 16px;
424
+ height: 16px;
425
+ border-radius: 50%;
426
+ background: var(--primary);
427
+ cursor: pointer;
428
+ }
429
+
430
+ .copy-indicator {
431
+ position: absolute;
432
+ top: 0.5rem;
433
+ right: 0.5rem;
434
+ background: var(--secondary);
435
+ color: white;
436
+ padding: 0.25rem 0.75rem;
437
+ border-radius: 4px;
438
+ font-size: 0.75rem;
439
+ opacity: 0;
440
+ transition: opacity 0.3s;
441
+ pointer-events: none;
442
+ }
443
+
444
+ .copy-indicator.show { opacity: 1; }
445
+
446
+ /* ===== CSS PLAYGROUND MODAL ===== */
447
+ .playground-modal {
448
+ position: fixed;
449
+ top: 0;
450
+ left: 0;
451
+ width: 100%;
452
+ height: 100%;
453
+ background: rgba(0, 0, 0, 0.8);
454
+ backdrop-filter: blur(5px);
455
+ z-index: 1000;
456
+ display: none;
457
+ place-items: center;
458
+ padding: 2rem;
459
+ }
460
+
461
+ .playground-modal.active { display: grid; }
462
+
463
+ .playground-content {
464
+ background: var(--darker);
465
+ border: 1px solid rgba(255, 255, 255, 0.1);
466
+ border-radius: var(--border-radius);
467
+ max-width: 1200px;
468
+ width: 100%;
469
+ max-height: 90vh;
470
+ overflow-y: auto;
471
+ display: grid;
472
+ grid-template-columns: 1fr 1fr;
473
+ gap: 2rem;
474
+ padding: 2rem;
475
+ }
476
+
477
+ @media (max-width: 900px) {
478
+ .playground-content {
479
+ grid-template-columns: 1fr;
480
+ }
481
+ }
482
+
483
+ .playground-editor,
484
+ .playground-preview {
485
+ display: flex;
486
+ flex-direction: column;
487
+ gap: 1rem;
488
+ }
489
+
490
+ .preview-iframe {
491
+ background: white;
492
+ border: 1px solid rgba(255, 255, 255, 0.1);
493
+ border-radius: 8px;
494
+ min-height: 400px;
495
+ width: 100%;
496
+ }
497
+
498
+ .modal-close {
499
+ position: absolute;
500
+ top: 1rem;
501
+ right: 1rem;
502
+ background: var(--danger);
503
+ color: white;
504
+ border: none;
505
+ width: 40px;
506
+ height: 40px;
507
+ border-radius: 50%;
508
+ cursor: pointer;
509
+ font-size: 1.25rem;
510
+ transition: var(--transition);
511
+ }
512
+
513
+ .modal-close:hover {
514
+ transform: rotate(90deg);
515
+ background: #dc2626;
516
+ }
517
+
518
+ /* ===== TOOLBAR ===== */
519
+ .css-toolbar {
520
+ background: rgba(255, 255, 255, 0.05);
521
+ border: 1px solid rgba(255, 255, 255, 0.1);
522
+ border-radius: var(--border-radius);
523
+ padding: 1rem;
524
+ margin-bottom: 2rem;
525
+ display: flex;
526
+ gap: 1rem;
527
+ flex-wrap: wrap;
528
+ align-items: center;
529
+ }
530
+
531
+ .toolbar-group {
532
+ display: flex;
533
+ gap: 0.5rem;
534
+ align-items: center;
535
+ }
536
+
537
+ .toolbar-group label {
538
+ font-size: 0.875rem;
539
+ color: var(--gray);
540
+ }
541
+
542
+ .selected-counter {
543
+ background: var(--warning);
544
+ color: var(--darker);
545
+ padding: 0.25rem 0.75rem;
546
+ border-radius: 20px;
547
+ font-weight: 700;
548
+ font-size: 0.875rem;
549
+ }
550
+
551
+ /* ===== ARCHIVE LIST ===== */
552
+ .archive-list {
553
+ display: grid;
554
+ gap: 1rem;
555
+ margin-top: 2rem;
556
+ }
557
+
558
+ .archive-item {
559
+ background: rgba(255, 255, 255, 0.05);
560
+ border: 1px solid rgba(255, 255, 255, 0.1);
561
+ border-radius: 8px;
562
+ padding: 1.5rem;
563
+ display: flex;
564
+ justify-content: space-between;
565
+ align-items: center;
566
+ transition: var(--transition);
567
+ }
568
+
569
+ .archive-item:hover {
570
+ background: rgba(255, 255, 255, 0.08);
571
+ transform: translateX(4px);
572
+ }
573
+
574
+ .archive-info h4 { margin-bottom: 0.25rem; }
575
+
576
+ .archive-meta {
577
+ color: var(--gray);
578
+ font-size: 0.875rem;
579
+ }
580
+
581
+ .search-box {
582
+ width: 100%;
583
+ max-width: 400px;
584
+ background: rgba(255, 255, 255, 0.05);
585
+ border: 1px solid rgba(255, 255, 255, 0.1);
586
+ border-radius: 8px;
587
+ padding: 0.75rem 1rem;
588
+ color: var(--light);
589
+ font-size: 1rem;
590
+ transition: var(--transition);
591
+ }
592
+
593
+ .search-box:focus {
594
+ outline: none;
595
+ border-color: var(--primary);
596
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
597
+ }
598
+
599
+ .search-container {
600
+ position: relative;
601
+ max-width: 400px;
602
+ }
603
+
604
+ /* ===== SETTINGS ===== */
605
+ .settings-grid {
606
+ display: grid;
607
+ gap: 2rem;
608
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
609
+ margin-top: 2rem;
610
+ }
611
+
612
+ .setting-card {
613
+ background: rgba(255, 255, 255, 0.05);
614
+ border: 1px solid rgba(255, 255, 255, 0.1);
615
+ border-radius: var(--border-radius);
616
+ padding: 1.5rem;
617
+ }
618
+
619
+ .setting-title {
620
+ font-size: 1.125rem;
621
+ font-weight: 700;
622
+ margin-bottom: 1rem;
623
+ display: flex;
624
+ align-items: center;
625
+ gap: 0.5rem;
626
+ }
627
+
628
+ .toggle-switch {
629
+ position: relative;
630
+ width: 50px;
631
+ height: 24px;
632
+ background: rgba(255, 255, 255, 0.2);
633
+ border-radius: 12px;
634
+ cursor: pointer;
635
+ transition: background 0.3s;
636
+ }
637
+
638
+ .toggle-switch.active { background: var(--primary); }
639
+
640
+ .toggle-slider {
641
+ position: absolute;
642
+ top: 2px;
643
+ left: 2px;
644
+ width: 20px;
645
+ height: 20px;
646
+ background: white;
647
+ border-radius: 50%;
648
+ transition: transform 0.3s;
649
+ box-shadow: var(--shadow-sm);
650
+ }
651
+
652
+ .toggle-switch.active .toggle-slider { transform: translateX(26px); }
653
+
654
+ .setting-row {
655
+ display: flex;
656
+ justify-content: space-between;
657
+ align-items: center;
658
+ padding: 0.75rem 0;
659
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
660
+ }
661
+
662
+ .setting-row:last-child { border-bottom: none; }
663
+
664
+ /* ===== PROGRESS BAR ===== */
665
+ .progress-bar {
666
+ position: fixed;
667
+ top: 0;
668
+ left: 0;
669
+ width: 100%;
670
+ height: 3px;
671
+ background: var(--primary);
672
+ transform: scaleX(0);
673
+ transform-origin: left;
674
+ transition: transform 0.3s;
675
+ z-index: 200;
676
+ }
677
+
678
+ .progress-bar.active { transform: scaleX(1); }
679
+
680
+ /* ===== NOTIFICATIONS ===== */
681
+ .notification {
682
+ position: fixed;
683
+ bottom: 2rem;
684
+ right: 2rem;
685
+ background: var(--darker);
686
+ border: 1px solid rgba(255, 255, 255, 0.1);
687
+ border-radius: 8px;
688
+ padding: 1rem 1.5rem;
689
+ box-shadow: var(--shadow-xl);
690
+ transform: translateY(100px);
691
+ opacity: 0;
692
+ transition: var(--transition);
693
+ z-index: 150;
694
+ max-width: 400px;
695
+ }
696
+
697
+ .notification.show {
698
+ transform: translateY(0);
699
+ opacity: 1;
700
+ }
701
+
702
+ .notification.success { border-left: 4px solid var(--secondary); }
703
+ .notification.error { border-left: 4px solid var(--danger); }
704
+ .notification.info { border-left: 4px solid var(--primary); }
705
+
706
+ /* ===== LOADING SPINNER ===== */
707
+ .spinner {
708
+ width: 40px;
709
+ height: 40px;
710
+ border: 3px solid rgba(255, 255, 255, 0.1);
711
+ border-top-color: var(--primary);
712
+ border-radius: 50%;
713
+ animation: spin 1s linear infinite;
714
+ margin: 2rem auto;
715
+ }
716
+
717
+ @keyframes spin { to { transform: rotate(360deg); } }
718
+
719
+ /* ===== RESPONSIVE ===== */
720
+ @media (max-width: 768px) {
721
+ .header { padding: 1rem; }
722
+ .main-content { padding: 1rem; }
723
+ .module-grid { grid-template-columns: 1fr; }
724
+ .action-buttons { flex-direction: column; }
725
+ .btn { width: 100%; justify-content: center; }
726
+ .css-toolbar { flex-direction: column; align-items: stretch; }
727
+ .toolbar-group { justify-content: space-between; }
728
+ }
729
+
730
+ /* ===== UTILITY CLASSES ===== */
731
+ .hidden { display: none !important; }
732
+ .fade-in { animation: fadeIn 0.3s ease-in-out; }
733
+ .text-muted { color: var(--gray); }
734
+ .mb-2 { margin-bottom: 0.5rem; }
735
+ .mb-4 { margin-bottom: 1rem; }
736
+ .mt-4 { margin-top: 1rem; }
737
+ </style>
738
  </head>
739
+
740
  <body>
741
+ <div class="progress-bar" id="progressBar"></div>
742
+
743
+ <header class="header">
744
+ <div class="logo-section">
745
+ <div class="logo">CF</div>
746
+ <div class="brand">CodeFlow Pro CSS</div>
747
+ </div>
748
+ <nav class="nav-tabs">
749
+ <button class="tab-btn active" data-tab="files">
750
+ <i class="fas fa-folder-open"></i> Dateien
751
+ <span class="badge" id="fileCount">0</span>
752
+ </button>
753
+ <button class="tab-btn" data-tab="modules">
754
+ <i class="fas fa-puzzle-piece"></i> CSS Module
755
+ <span class="badge" id="moduleCount">0</span>
756
+ </button>
757
+ <button class="tab-btn" data-tab="archive">
758
+ <i class="fas fa-archive"></i> Archiv
759
+ <span class="badge" id="archiveCount">0</span>
760
+ </button>
761
+ <button class="tab-btn" data-tab="settings">
762
+ <i class="fas fa-cog"></i> Einstellungen
763
+ </button>
764
+ </nav>
765
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">
766
+ Built with anycoder
767
+ </a>
768
+ </header>
769
+
770
+ <main class="main-content">
771
+ <!-- FILES TAB -->
772
+ <div class="tab-panel active" id="files-tab">
773
+ <h2 class="mb-4">CSS Dateien verarbeiten</h2>
774
+
775
+ <div class="upload-zone" id="uploadZone">
776
+ <div class="upload-icon">
777
+ <i class="fas fa-cloud-upload-alt"></i>
778
  </div>
779
+ <div class="upload-text">CSS Dateien hier ablegen oder klicken</div>
780
+ <div class="upload-hint">Unterstützt: .css Dateien oder CSS Code</div>
781
+ <input type="file" id="fileInput" class="file-input" accept=".css" multiple>
782
+ </div>
783
+
784
+ <div class="action-buttons">
785
+ <button class="btn" id="selectFilesBtn">
786
+ <i class="fas fa-file"></i> Dateien auswählen
787
+ </button>
788
+ <button class="btn btn-secondary" id="pasteCssBtn">
789
+ <i class="fas fa-paste"></i> CSS Einfügen
790
+ </button>
791
+ <button class="btn btn-secondary" id="processBtn" disabled>
792
+ <i class="fas fa-cogs"></i> Verarbeiten
793
+ </button>
794
+ <button class="btn btn-danger" id="clearBtn">
795
+ <i class="fas fa-trash"></i> Alle löschen
796
+ </button>
797
+ </div>
798
+
799
+ <div id="fileList" class="mt-4"></div>
800
+ </div>
801
+
802
+ <!-- MODULES TAB -->
803
+ <div class="tab-panel" id="modules-tab">
804
+ <h2 class="mb-4">CSS Module & Playground</h2>
805
+
806
+ <div class="css-toolbar">
807
+ <div class="toolbar-group">
808
+ <label>Ausgewählt:</label>
809
+ <span class="selected-counter" id="selectedCount">0</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
810
  </div>
811
+ <div class="toolbar-group">
812
+ <button class="btn btn-secondary" id="selectAllBtn">
813
+ <i class="fas fa-check-square"></i> Alle
814
+ </button>
815
+ <button class="btn btn-secondary" id="deselectAllBtn">
816
+ <i class="fas fa-square"></i> Keine
817
+ </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
818
  </div>
819
+ <div class="toolbar-group">
820
+ <button class="btn" id="combineSelectedBtn">
821
+ <i class="fas fa-object-group"></i> Zusammenführen
822
+ </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
823
  </div>
824
+ <div class="toolbar-group">
825
+ <button class="btn btn-secondary" id="exportHtmlViewBtn">
826
+ <i class="fas fa-file-code"></i> HTML View
827
+ </button>
828
+ <button class="btn btn-secondary" id="recodeStylesheetBtn">
829
+ <i class="fas fa-sync-alt"></i> Stylesheet Recode
830
+ </button>
831
+ </div>
832
+ <div class="toolbar-group">
833
+ <button class="btn btn-danger" id="removeDuplicatesBtn">
834
+ <i class="fas fa-clone"></i> Duplikate
835
+ </button>
836
+ </div>
837
+ </div>
838
+
839
+ <div class="search-container">
840
+ <input type="text" class="search-box" id="moduleSearch" placeholder="Module suchen...">
841
+ </div>
842
+
843
+ <div class="module-grid" id="moduleGrid"></div>
844
+ </div>
845
+
846
+ <!-- ARCHIVE TAB -->
847
+ <div class="tab-panel" id="archive-tab">
848
+ <h2 class="mb-4">CSS Archiv</h2>
849
+
850
+ <div class="search-container">
851
+ <input type="text" class="search-box" id="archiveSearch" placeholder="Archiv durchsuchen...">
852
+ </div>
853
+
854
+ <div class="action-buttons">
855
+ <button class="btn" id="exportArchiveBtn">
856
+ <i class="fas fa-file-archive"></i> Archiv exportieren
857
+ </button>
858
+ <button class="btn btn-danger" id="clearArchiveBtn">
859
+ <i class="fas fa-broom"></i> Archiv leeren
860
+ </button>
861
+ </div>
862
+
863
+ <div class="archive-list" id="archiveList"></div>
864
+ </div>
865
+
866
+ <!-- SETTINGS TAB -->
867
+ <div class="tab-panel" id="settings-tab">
868
+ <h2 class="mb-4">CSS Playground Einstellungen</h2>
869
+
870
+ <div class="settings-grid">
871
+ <div class="setting-card">
872
+ <h3 class="setting-title">
873
+ <i class="fas fa-magic"></i> Automatisierung
874
+ </h3>
875
+ <div class="setting-row">
876
+ <span>Auto-Speicherung</span>
877
+ <div class="toggle-switch active" data-setting="autoSave"></div>
878
+ </div>
879
+ <div class="setting-row">
880
+ <span>Auto-Benennung</span>
881
+ <div class="toggle-switch active" data-setting="autoNaming"></div>
882
+ </div>
883
+ <div class="setting-row">
884
+ <span>Duplikat-Prüfung</span>
885
+ <div class="toggle-switch active" data-setting="duplicateCheck"></div>
886
+ </div>
887
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
888
 
889
+ <div class="setting-card">
890
+ <h3 class="setting-title">
891
+ <i class="fas fa-palette"></i> CSS Verarbeitung
892
+ </h3>
893
+ <div class="setting-row">
894
+ <span>CSS-Variablen extrahieren</span>
895
+ <div class="toggle-switch active" data-setting="extractCssVars"></div>
896
+ </div>
897
+ <div class="setting-row">
898
+ <span>Farben optimieren</span>
899
+ <div class="toggle-switch" data-setting="optimizeColors"></div>
900
+ </div>
901
+ <div class="setting-row">
902
+ <span>Responsive Regeln</span>
903
+ <div class="toggle-switch active" data-setting="responsiveRules"></div>
904
+ </div>
905
+ </div>
906
 
907
+ <div class="setting-card">
908
+ <h3 class="setting-title">
909
+ <i class="fas fa-history"></i> Historie
910
+ </h3>
911
+ <div class="setting-row">
912
+ <span>Such-Historie speichern</span>
913
+ <div class="toggle-switch active" data-setting="searchHistory"></div>
914
+ </div>
915
+ <div class="setting-row">
916
+ <span>Letzte Sitzung wiederherstellen</span>
917
+ <div class="toggle-switch active" data-setting="restoreSession"></div>
918
+ </div>
919
+ <div class="setting-row">
920
+ <button class="btn" id="clearHistoryBtn" style="width: 100%;">
921
+ <i class="fas fa-eraser"></i> Historie leeren
922
+ </button>
923
+ </div>
924
+ </div>
925
+ </div>
926
+ </div>
927
+ </main>
928
+
929
+ <!-- CSS Playground Modal -->
930
+ <div class="playground-modal" id="playgroundModal">
931
+ <button class="modal-close" id="closePlayground">
932
+ <i class="fas fa-times"></i>
933
+ </button>
934
+ <div class="playground-content">
935
+ <div class="playground-editor">
936
+ <h3>CSS Editor</h3>
937
+ <div class="css-editor" id="playgroundEditor" contenteditable="true"></div>
938
+ <div class="css-controls" id="cssControls"></div>
939
+ </div>
940
+ <div class="playground-preview">
941
+ <h3>Live Vorschau</h3>
942
+ <iframe class="preview-iframe" id="previewFrame"></iframe>
943
+ <div class="action-buttons">
944
+ <button class="btn" id="applyPlaygroundChanges">
945
+ <i class="fas fa-check"></i> Änderungen übernehmen
946
+ </button>
947
+ <button class="btn btn-secondary" id="resetPlayground">
948
+ <i class="fas fa-undo"></i> Zurücksetzen
949
+ </button>
950
+ </div>
951
+ </div>
952
+ </div>
953
+ </div>
954
+
955
+ <!-- CSS Paste Modal -->
956
+ <div class="playground-modal" id="pasteModal">
957
+ <button class="modal-close" id="closePasteModal">
958
+ <i class="fas fa-times"></i>
959
+ </button>
960
+ <div class="playground-content" style="grid-template-columns: 1fr;">
961
+ <div>
962
+ <h3>CSS Code Einfügen</h3>
963
+ <div class="css-editor" id="pasteEditor" contenteditable="true" style="min-height: 300px;"></div>
964
+ <div class="action-buttons">
965
+ <button class="btn" id="processPastedCss">
966
+ <i class="fas fa-cogs"></i> Verarbeiten
967
+ </button>
968
+ </div>
969
+ </div>
970
+ </div>
971
+ </div>
972
+
973
+ <div class="notification" id="notification"></div>
974
+
975
+ <script>
976
+ // ===== MODERN JAVASCRIPT ES2022+ =====
977
+ class CodeFlowApp {
978
+ #files = new Map();
979
+ #modules = new Map();
980
+ #archive = new Map();
981
+ #selectedModules = new Set();
982
+ #settings = new Map([
983
+ ['autoSave', true],
984
+ ['autoNaming', true],
985
+ ['duplicateCheck', true],
986
+ ['extractCssVars', true],
987
+ ['optimizeColors', false],
988
+ ['responsiveRules', true],
989
+ ['searchHistory', true],
990
+ ['restoreSession', true]
991
+ ]);
992
+ #history = { searches: [], processedFiles: [] };
993
+ #currentPlaygroundId = null;
994
+
995
+ constructor() {
996
+ this.#init();
997
+ this.#loadFromStorage();
998
+ this.#setupEventListeners();
999
+ this.#setupAutoSave();
1000
+ }
1001
+
1002
+ // ===== INITIALIZATION =====
1003
+ #init() {
1004
+ console.log('🚀 CodeFlow Pro CSS Playground initialisiert');
1005
+ this.#updateBadgeCounts();
1006
+ this.#renderArchive();
1007
+ }
1008
+
1009
+ // ===== STORAGE MANAGEMENT =====
1010
+ #saveToStorage() {
1011
+ if (!this.#settings.get('autoSave')) return;
1012
+
1013
+ const data = {
1014
+ modules: Array.from(this.#modules.entries()),
1015
+ archive: Array.from(this.#archive.entries()),
1016
+ settings: Array.from(this.#settings.entries()),
1017
+ history: this.#history,
1018
+ timestamp: Date.now()
1019
+ };
1020
+
1021
+ localStorage.setItem('codeflow-css-data', JSON.stringify(data));
1022
+ this.#showNotification('Auto-gespeichert', 'info');
1023
+ }
1024
+
1025
+ #loadFromStorage() {
1026
+ if (!this.#settings.get('restoreSession')) return;
1027
+
1028
+ const saved = localStorage.getItem('codeflow-css-data');
1029
+ if (!saved) return;
1030
+
1031
+ try {
1032
+ const data = JSON.parse(saved);
1033
+ this.#modules = new Map(data.modules || []);
1034
+ this.#archive = new Map(data.archive || []);
1035
+ this.#settings = new Map(data.settings || this.#settings);
1036
+ this.#history = data.history || this.#history;
1037
+
1038
+ this.#updateBadgeCounts();
1039
+ this.#renderArchive();
1040
+ this.#applySettings();
1041
+ } catch (e) {
1042
+ console.error('Fehler beim Laden:', e);
1043
+ }
1044
+ }
1045
+
1046
+ // ===== EVENT LISTENERS =====
1047
+ #setupEventListeners() {
1048
+ // Tabs
1049
+ document.querySelectorAll('.tab-btn').forEach(btn => {
1050
+ btn.addEventListener('click', (e) => this.#switchTab(e.target.dataset.tab));
1051
+ });
1052
+
1053
+ // Upload Zone
1054
+ const zone = document.getElementById('uploadZone');
1055
+ zone.addEventListener('click', () => document.getElementById('fileInput').click());
1056
+ zone.addEventListener('dragover', this.#handleDragOver.bind(this));
1057
+ zone.addEventListener('dragleave', this.#handleDragLeave.bind(this));
1058
+ zone.addEventListener('drop', this.#handleDrop.bind(this));
1059
+
1060
+ // File Input
1061
+ document.getElementById('fileInput').addEventListener('change', this.#handleFileSelect.bind(this));
1062
+ document.getElementById('selectFilesBtn').addEventListener('click', () => {
1063
+ document.getElementById('fileInput').click();
1064
+ });
1065
+ document.getElementById('pasteCssBtn').addEventListener('click', () => {
1066
+ document.getElementById('pasteModal').classList.add('active');
1067
+ });
1068
+
1069
+ // Action Buttons
1070
+ document.getElementById('processBtn').addEventListener('click', () => this.#processFiles());
1071
+ document.getElementById('clearBtn').addEventListener('click', () => this.#clearFiles());
1072
+ document.getElementById('selectAllBtn').addEventListener('click', () => this.#selectAllModules());
1073
+ document.getElementById('deselectAllBtn').addEventListener('click', () => this.#deselectAllModules());
1074
+ document.getElementById('combineSelectedBtn').addEventListener('click', () => this.#combineSelected());
1075
+ document.getElementById('exportHtmlViewBtn').addEventListener('click', () => this.#exportHtmlView());
1076
+ document.getElementById('recodeStylesheetBtn').addEventListener('click', () => this.#recodeStylesheet());
1077
+ document.getElementById('removeDuplicatesBtn').addEventListener('click', () => this.#removeDuplicates());
1078
+ document.getElementById('clearArchiveBtn').addEventListener('click', () => this.#clearArchive());
1079
+ document.getElementById('exportArchiveBtn').addEventListener('click', () => this.#exportArchive());
1080
+ document.getElementById('clearHistoryBtn').addEventListener('click', () => this.#clearHistory());
1081
+
1082
+ // Search
1083
+ document.getElementById('moduleSearch').addEventListener('input', (e) => this.#handleSearch(e.target.value));
1084
+
1085
+ // Settings
1086
+ document.querySelectorAll('.toggle-switch').forEach(toggle => {
1087
+ toggle.addEventListener('click', (e) => this.#toggleSetting(e.target.dataset.setting));
1088
+ });
1089
+
1090
+ // Playground
1091
+ document.getElementById('closePlayground').addEventListener('click', () => {
1092
+ document.getElementById('playgroundModal').classList.remove('active');
1093
+ });
1094
+ document.getElementById('applyPlaygroundChanges').addEventListener('click', () => this.#applyPlaygroundChanges());
1095
+ document.getElementById('resetPlayground').addEventListener('click', () => this.#resetPlayground());
1096
+ document.getElementById('playgroundEditor').addEventListener('input', () => this.#updatePreview());
1097
+
1098
+ // Paste Modal
1099
+ document.getElementById('closePasteModal').addEventListener('click', () => {
1100
+ document.getElementById('pasteModal').classList.remove('active');
1101
+ });
1102
+ document.getElementById('processPastedCss').addEventListener('click', () => this.#processPastedCss());
1103
+
1104
+ // Auto-save on input
1105
+ document.addEventListener('input', () => this.#debouncedSave());
1106
+ }
1107
+
1108
+ // ===== FILE HANDLING =====
1109
+ async #handleFileSelect(e) {
1110
+ const files = Array.from(e.target.files);
1111
+ await this.#addFiles(files);
1112
+ }
1113
+
1114
+ #handleDragOver(e) {
1115
+ e.preventDefault();
1116
+ e.currentTarget.classList.add('dragover');
1117
+ }
1118
+
1119
+ #handleDragLeave(e) {
1120
+ e.currentTarget.classList.remove('dragover');
1121
+ }
1122
+
1123
+ async #handleDrop(e) {
1124
+ e.preventDefault();
1125
+ e.currentTarget.classList.remove('dragover');
1126
+
1127
+ const items = Array.from(e.dataTransfer.items);
1128
+ const files = [];
1129
+
1130
+ for (const item of items) {
1131
+ if (item.kind === 'file') {
1132
+ const file = item.getAsFile();
1133
+ if (item.webkitGetAsEntry) {
1134
+ const entry = item.webkitGetAsEntry();
1135
+ if (entry?.isDirectory) {
1136
+ await this.#readDirectory(entry, files);
1137
+ } else {
1138
+ files.push(file);
1139
+ }
1140
+ } else {
1141
+ files.push(file);
1142
  }
1143
+ }
1144
+ }
1145
+
1146
+ await this.#addFiles(files);
1147
+ }
1148
+
1149
+ async #readDirectory(entry, files) {
1150
+ const reader = entry.createReader();
1151
+ const entries = await new Promise(resolve => reader.readEntries(resolve));
1152
+
1153
+ for (const subEntry of entries) {
1154
+ if (subEntry.isDirectory) {
1155
+ await this.#readDirectory(subEntry, files);
1156
+ } else {
1157
+ const file = await new Promise(resolve => subEntry.file(resolve));
1158
+ files.push(file);
1159
+ }
1160
+ }
1161
+ }
1162
+
1163
+ async #addFiles(files) {
1164
+ const cssFiles = files.filter(f => f.type === 'text/css' || f.name.endsWith('.css'));
1165
+
1166
+ for (const file of cssFiles) {
1167
+ this.#files.set(file.name, {
1168
+ file,
1169
+ id: crypto.randomUUID(),
1170
+ processed: false,
1171
+ timestamp: Date.now()
1172
+ });
1173
+ }
1174
+
1175
+ this.#renderFileList();
1176
+ this.#updateBadgeCounts();
1177
+ this.#showNotification(`${cssFiles.length} CSS-Dateien hinzugefügt`, 'success');
1178
+ }
1179
+
1180
+ #renderFileList() {
1181
+ const container = document.getElementById('fileList');
1182
+ if (this.#files.size === 0) {
1183
+ container.innerHTML = '<p class="text-muted">Keine CSS-Dateien ausgewählt</p>';
1184
+ document.getElementById('processBtn').disabled = true;
1185
+ return;
1186
+ }
1187
+
1188
+ container.innerHTML = Array.from(this.#files.values()).map(fileObj => `
1189
+ <div class="archive-item fade-in">
1190
+ <div class="archive-info">
1191
+ <h4>${fileObj.file.name}</h4>
1192
+ <div class="archive-meta">
1193
+ ${this.#formatBytes(fileObj.file.size)} • ${new Date(fileObj.timestamp).toLocaleString()}
1194
+ </div>
1195
+ </div>
1196
+ <button class="icon-btn" onclick="app.#removeFile('${fileObj.id}')">
1197
+ <i class="fas fa-times"></i>
1198
+ </button>
1199
+ </div>
1200
+ `).join('');
1201
+
1202
+ document.getElementById('processBtn').disabled = false;
1203
+ }
1204
+
1205
+ #removeFile(id) {
1206
+ const entry = Array.from(this.#files.entries()).find(([, v]) => v