clou-lang 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,682 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Clou Playground - Build Websites Live</title>
7
+ <style>
8
+ * { margin: 0; padding: 0; box-sizing: border-box; }
9
+
10
+ :root {
11
+ --bg: #0f0f23;
12
+ --bg2: #1a1a35;
13
+ --bg3: #252545;
14
+ --text: #e0e0e0;
15
+ --accent: #6C63FF;
16
+ --accent2: #00e5ff;
17
+ --border: #2a2a4a;
18
+ --green: #00ff88;
19
+ --red: #ff6b6b;
20
+ }
21
+
22
+ body {
23
+ background: var(--bg);
24
+ color: var(--text);
25
+ font-family: 'Segoe UI', system-ui, sans-serif;
26
+ height: 100vh;
27
+ overflow: hidden;
28
+ display: flex;
29
+ flex-direction: column;
30
+ }
31
+
32
+ /* ── Header ── */
33
+ .header {
34
+ display: flex;
35
+ align-items: center;
36
+ justify-content: space-between;
37
+ padding: 10px 20px;
38
+ background: var(--bg2);
39
+ border-bottom: 1px solid var(--border);
40
+ height: 52px;
41
+ flex-shrink: 0;
42
+ }
43
+
44
+ .logo {
45
+ font-size: 1.3em;
46
+ font-weight: 700;
47
+ background: linear-gradient(135deg, var(--accent), var(--accent2));
48
+ -webkit-background-clip: text;
49
+ -webkit-text-fill-color: transparent;
50
+ background-clip: text;
51
+ letter-spacing: -0.5px;
52
+ }
53
+
54
+ .logo span {
55
+ -webkit-text-fill-color: #888;
56
+ font-weight: 400;
57
+ font-size: 0.75em;
58
+ margin-left: 8px;
59
+ }
60
+
61
+ .header-actions {
62
+ display: flex;
63
+ gap: 8px;
64
+ align-items: center;
65
+ }
66
+
67
+ .theme-select {
68
+ padding: 6px 12px;
69
+ background: var(--bg3);
70
+ border: 1px solid var(--border);
71
+ border-radius: 6px;
72
+ color: var(--text);
73
+ font-size: 13px;
74
+ cursor: pointer;
75
+ outline: none;
76
+ }
77
+
78
+ .theme-select:focus { border-color: var(--accent); }
79
+
80
+ .btn {
81
+ padding: 6px 14px;
82
+ border: 1px solid var(--border);
83
+ border-radius: 6px;
84
+ background: var(--bg3);
85
+ color: var(--text);
86
+ font-size: 13px;
87
+ cursor: pointer;
88
+ transition: all 0.15s;
89
+ }
90
+
91
+ .btn:hover { background: var(--accent); color: white; border-color: var(--accent); }
92
+ .btn-accent { background: var(--accent); color: white; border-color: var(--accent); }
93
+ .btn-accent:hover { background: #5a52d5; }
94
+
95
+ /* ── Examples Bar ── */
96
+ .examples-bar {
97
+ display: flex;
98
+ gap: 6px;
99
+ padding: 8px 20px;
100
+ background: var(--bg);
101
+ border-bottom: 1px solid var(--border);
102
+ overflow-x: auto;
103
+ flex-shrink: 0;
104
+ }
105
+
106
+ .example-btn {
107
+ padding: 4px 12px;
108
+ border: 1px solid var(--border);
109
+ border-radius: 20px;
110
+ background: transparent;
111
+ color: #888;
112
+ font-size: 12px;
113
+ cursor: pointer;
114
+ white-space: nowrap;
115
+ transition: all 0.15s;
116
+ }
117
+
118
+ .example-btn:hover { color: var(--accent); border-color: var(--accent); }
119
+ .example-btn.active { color: var(--accent); border-color: var(--accent); background: rgba(108, 99, 255, 0.1); }
120
+
121
+ /* ── Main Split ── */
122
+ .main {
123
+ display: flex;
124
+ flex: 1;
125
+ overflow: hidden;
126
+ }
127
+
128
+ /* ── Editor Panel ── */
129
+ .editor-panel {
130
+ width: 45%;
131
+ display: flex;
132
+ flex-direction: column;
133
+ border-right: 1px solid var(--border);
134
+ }
135
+
136
+ .panel-header {
137
+ padding: 8px 16px;
138
+ font-size: 12px;
139
+ font-weight: 600;
140
+ text-transform: uppercase;
141
+ letter-spacing: 1px;
142
+ color: #666;
143
+ background: var(--bg2);
144
+ border-bottom: 1px solid var(--border);
145
+ display: flex;
146
+ justify-content: space-between;
147
+ align-items: center;
148
+ }
149
+
150
+ .status {
151
+ font-size: 11px;
152
+ font-weight: 400;
153
+ text-transform: none;
154
+ letter-spacing: 0;
155
+ }
156
+
157
+ .status-ok { color: var(--green); }
158
+ .status-err { color: var(--red); }
159
+
160
+ #editor {
161
+ flex: 1;
162
+ width: 100%;
163
+ background: var(--bg);
164
+ color: #e0e0e0;
165
+ border: none;
166
+ outline: none;
167
+ padding: 16px;
168
+ font-family: 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Consolas', monospace;
169
+ font-size: 14px;
170
+ line-height: 1.6;
171
+ resize: none;
172
+ tab-size: 4;
173
+ -moz-tab-size: 4;
174
+ white-space: pre;
175
+ overflow: auto;
176
+ }
177
+
178
+ #editor::placeholder { color: #444; }
179
+
180
+ /* ── Preview Panel ── */
181
+ .preview-panel {
182
+ flex: 1;
183
+ display: flex;
184
+ flex-direction: column;
185
+ background: white;
186
+ }
187
+
188
+ #preview {
189
+ flex: 1;
190
+ border: none;
191
+ width: 100%;
192
+ height: 100%;
193
+ background: white;
194
+ }
195
+
196
+ /* ── Error Toast ── */
197
+ .error-bar {
198
+ display: none;
199
+ padding: 8px 16px;
200
+ background: rgba(255, 107, 107, 0.1);
201
+ border-top: 1px solid rgba(255, 107, 107, 0.3);
202
+ color: var(--red);
203
+ font-family: monospace;
204
+ font-size: 13px;
205
+ max-height: 80px;
206
+ overflow-y: auto;
207
+ }
208
+
209
+ .error-bar.visible { display: block; }
210
+
211
+ /* ── Resize Handle ── */
212
+ .resize-handle {
213
+ width: 4px;
214
+ cursor: col-resize;
215
+ background: var(--border);
216
+ transition: background 0.15s;
217
+ }
218
+ .resize-handle:hover { background: var(--accent); }
219
+
220
+ /* ── Responsive ── */
221
+ @media (max-width: 768px) {
222
+ .main { flex-direction: column; }
223
+ .editor-panel { width: 100%; height: 50%; border-right: none; border-bottom: 1px solid var(--border); }
224
+ .resize-handle { display: none; }
225
+ }
226
+ </style>
227
+ </head>
228
+ <body>
229
+
230
+ <div class="header">
231
+ <div class="logo">Clou Playground <span>v0.2</span></div>
232
+ <div class="header-actions">
233
+ <select class="theme-select" id="themeSelect">
234
+ <option value="">No Theme</option>
235
+ </select>
236
+ <button class="btn" id="copyBtn">Copy HTML</button>
237
+ <button class="btn btn-accent" id="downloadBtn">Download</button>
238
+ </div>
239
+ </div>
240
+
241
+ <div class="examples-bar" id="examplesBar"></div>
242
+
243
+ <div class="main">
244
+ <div class="editor-panel" id="editorPanel">
245
+ <div class="panel-header">
246
+ <span>Editor — .clou</span>
247
+ <span class="status" id="status"></span>
248
+ </div>
249
+ <textarea id="editor" spellcheck="false" placeholder="Write your Clou code here..."></textarea>
250
+ <div class="error-bar" id="errorBar"></div>
251
+ </div>
252
+ <div class="resize-handle" id="resizeHandle"></div>
253
+ <div class="preview-panel">
254
+ <div class="panel-header">Preview</div>
255
+ <iframe id="preview" sandbox="allow-scripts allow-modals"></iframe>
256
+ </div>
257
+ </div>
258
+
259
+ <script src="clou-browser.js"></script>
260
+ <script>
261
+ (function() {
262
+ const editor = document.getElementById('editor');
263
+ const preview = document.getElementById('preview');
264
+ const status = document.getElementById('status');
265
+ const errorBar = document.getElementById('errorBar');
266
+ const themeSelect = document.getElementById('themeSelect');
267
+ const copyBtn = document.getElementById('copyBtn');
268
+ const downloadBtn = document.getElementById('downloadBtn');
269
+ const examplesBar = document.getElementById('examplesBar');
270
+
271
+ let lastHtml = '';
272
+ let compileTimer = null;
273
+
274
+ // ── Populate Themes ──
275
+ Clou.getThemeNames().forEach(name => {
276
+ const opt = document.createElement('option');
277
+ opt.value = name;
278
+ opt.textContent = name.charAt(0).toUpperCase() + name.slice(1);
279
+ themeSelect.appendChild(opt);
280
+ });
281
+
282
+ // ── Examples ──
283
+ const examples = {
284
+ 'Hello World': `page "My First Website":
285
+ title "Hello Clou!"
286
+
287
+ box:
288
+ heading "Welcome!"
289
+ text "This is my first website made with Clou."
290
+ text "Edit this code on the left to see changes!"
291
+
292
+ button "Click me":
293
+ show message "Hello from Clou!"
294
+
295
+ style:
296
+ background color #f0f4f8
297
+ text color #333
298
+ button color #4A90D9
299
+ center`,
300
+
301
+ 'Landing Page': `set brand to "SpaceApp"
302
+
303
+ template feature(emoji, title, desc):
304
+ card:
305
+ icon "{emoji}"
306
+ heading "{title}"
307
+ text "{desc}"
308
+ animate slide
309
+
310
+ page "{brand} - Launch Your Ideas":
311
+ theme "midnight"
312
+
313
+ navbar "{brand}":
314
+ link "Features" to "#features"
315
+ link "Pricing" to "#pricing"
316
+ link "Start" to "#cta"
317
+
318
+ section "hero":
319
+ center
320
+ space 30
321
+ heading "Launch Your Ideas Into Space":
322
+ huge
323
+ animate fade
324
+ text "The fastest way to build and ship your next project.":
325
+ big
326
+ space 20
327
+ row:
328
+ center
329
+ button "Get Started":
330
+ show message "Welcome to {brand}!"
331
+ button "Learn More":
332
+ go to "#features"
333
+ space 30
334
+
335
+ section "features":
336
+ center
337
+ heading "Why {brand}?":
338
+ huge
339
+ space 20
340
+ grid:
341
+ use feature("⚡", "Blazing Fast", "Built for speed from the ground up.")
342
+ use feature("🔒", "Secure", "Enterprise-grade security by default.")
343
+ use feature("🎨", "Beautiful", "Stunning UI without the effort.")
344
+
345
+ section "cta":
346
+ center
347
+ card:
348
+ gradient #6C63FF to #00e5ff
349
+ padding 60
350
+ center
351
+ heading "Ready to Launch?":
352
+ huge
353
+ animate bounce
354
+ text "Start building for free today."
355
+ space 20
356
+ button "Start Now":
357
+ show message "Let's go!"`,
358
+
359
+ 'Portfolio': `set name to "Alex"
360
+
361
+ page "{name}'s Portfolio":
362
+ theme "glass"
363
+
364
+ navbar "{name}":
365
+ link "Work" to "#work"
366
+ link "About" to "#about"
367
+ link "Contact" to "#contact"
368
+
369
+ section "hero":
370
+ center
371
+ space 40
372
+ heading "Hi, I'm {name}":
373
+ huge
374
+ animate fade
375
+ text "Designer & Developer":
376
+ big
377
+ space 40
378
+
379
+ section "work":
380
+ center
381
+ heading "My Work":
382
+ huge
383
+ space 20
384
+ grid:
385
+ card:
386
+ heading "Project Alpha"
387
+ text "A mobile app for fitness tracking"
388
+ animate slide
389
+ card:
390
+ heading "Project Beta"
391
+ text "An e-commerce website redesign"
392
+ animate slide
393
+ card:
394
+ heading "Project Gamma"
395
+ text "A dashboard for data analytics"
396
+ animate slide
397
+
398
+ section "contact":
399
+ center
400
+ card:
401
+ center
402
+ padding 40
403
+ heading "Get In Touch"
404
+ space 10
405
+ input "Your email"
406
+ input "Your message"
407
+ space 10
408
+ button "Send":
409
+ show message "Thanks! I'll get back to you soon."
410
+
411
+ footer:
412
+ text "© 2026 {name}. Built with Clou."`,
413
+
414
+ 'Neon Theme': `page "Neon Vibes":
415
+ theme "neon"
416
+
417
+ navbar "NEON":
418
+ link "Home" to "#"
419
+ link "About" to "#"
420
+ link "Contact" to "#"
421
+
422
+ section "hero":
423
+ center
424
+ space 30
425
+ heading "Welcome to the Future":
426
+ huge
427
+ animate fade
428
+ text "Cyberpunk aesthetics. One line of code.":
429
+ big
430
+ space 20
431
+ button "Enter the Grid":
432
+ show message "Welcome, hacker."
433
+ space 30
434
+
435
+ grid:
436
+ card:
437
+ icon "🟢"
438
+ heading "Neon Glow"
439
+ text "Electric green on pure black."
440
+ animate slide
441
+ card:
442
+ icon "⚡"
443
+ heading "Gradient Text"
444
+ text "Headers shimmer with color."
445
+ animate slide
446
+ card:
447
+ icon "🌃"
448
+ heading "Dark Mode"
449
+ text "Easy on the eyes, hard to forget."
450
+ animate slide
451
+
452
+ footer:
453
+ text "Powered by Clou"`,
454
+
455
+ 'Candy Theme': `page "Sweet Shop":
456
+ theme "candy"
457
+
458
+ navbar "Sweet Shop":
459
+ link "Menu" to "#menu"
460
+ link "About" to "#about"
461
+ link "Order" to "#order"
462
+
463
+ section "hero":
464
+ center
465
+ space 30
466
+ icon "🍬"
467
+ heading "Life is Sweet":
468
+ huge
469
+ animate bounce
470
+ text "The cutest little candy shop on the internet.":
471
+ big
472
+ space 30
473
+
474
+ section "menu":
475
+ center
476
+ heading "Our Treats":
477
+ huge
478
+ space 20
479
+ grid:
480
+ card:
481
+ icon "🍩"
482
+ heading "Donuts"
483
+ text "Freshly glazed, always amazing."
484
+ animate slide
485
+ card:
486
+ icon "🧁"
487
+ heading "Cupcakes"
488
+ text "Fluffy clouds of sweetness."
489
+ animate slide
490
+ card:
491
+ icon "🍪"
492
+ heading "Cookies"
493
+ text "Crunchy on the outside, soft inside."
494
+ animate slide
495
+
496
+ section "order":
497
+ center
498
+ card:
499
+ center
500
+ padding 40
501
+ heading "Place an Order"
502
+ space 10
503
+ input "Your name"
504
+ input "What would you like?"
505
+ space 10
506
+ button "Order Now":
507
+ show message "Order placed! 🍬"
508
+
509
+ footer:
510
+ text "Sweet Shop © 2026 — Made with Clou"`,
511
+
512
+ 'Minimal': `page "Minimal":
513
+ theme "minimal"
514
+
515
+ section "main":
516
+ space 40
517
+ heading "Less is more.":
518
+ huge
519
+ animate fade
520
+ space 10
521
+ text "A clean canvas for your ideas. No noise. No distractions."
522
+ text "Just content that matters."
523
+ space 30
524
+ line
525
+ space 30
526
+ heading "Features"
527
+ space 10
528
+ list:
529
+ text "Clean typography"
530
+ text "Focused layout"
531
+ text "Black and white"
532
+ text "Zero clutter"
533
+ space 30
534
+ line
535
+ space 30
536
+ button "Get Started":
537
+ show message "Keep it simple."
538
+ space 40
539
+
540
+ footer:
541
+ text "Built with Clou — the simplest way to build websites."`,
542
+ };
543
+
544
+ // Create example buttons
545
+ Object.keys(examples).forEach((name, i) => {
546
+ const btn = document.createElement('button');
547
+ btn.className = 'example-btn' + (i === 0 ? ' active' : '');
548
+ btn.textContent = name;
549
+ btn.onclick = () => {
550
+ editor.value = examples[name];
551
+ document.querySelectorAll('.example-btn').forEach(b => b.classList.remove('active'));
552
+ btn.classList.add('active');
553
+ // Auto-detect theme
554
+ const themeMatch = examples[name].match(/theme\s+"(\w+)"/);
555
+ themeSelect.value = themeMatch ? themeMatch[1] : '';
556
+ compileAndRender();
557
+ };
558
+ examplesBar.appendChild(btn);
559
+ });
560
+
561
+ // ── Compile & Render ──
562
+ function compileAndRender() {
563
+ let source = editor.value;
564
+
565
+ // If theme selected and not already in code, inject it
566
+ const selectedTheme = themeSelect.value;
567
+ if (selectedTheme && !source.includes('theme "')) {
568
+ // Find page line and inject theme after it
569
+ const lines = source.split('\n');
570
+ let injected = false;
571
+ for (let i = 0; i < lines.length; i++) {
572
+ if (lines[i].trim().startsWith('page ')) {
573
+ // Find next indented line
574
+ const indent = lines[i + 1] ? lines[i + 1].match(/^(\s*)/)[1] : ' ';
575
+ lines.splice(i + 1, 0, indent + 'theme "' + selectedTheme + '"');
576
+ injected = true;
577
+ break;
578
+ }
579
+ }
580
+ if (!injected) {
581
+ source = 'theme "' + selectedTheme + '"\n' + source;
582
+ } else {
583
+ source = lines.join('\n');
584
+ }
585
+ }
586
+
587
+ try {
588
+ const result = Clou.buildClou(source);
589
+ lastHtml = result.html;
590
+
591
+ // Write to iframe
592
+ const doc = preview.contentDocument || preview.contentWindow.document;
593
+ doc.open();
594
+ doc.write(lastHtml);
595
+ doc.close();
596
+
597
+ status.textContent = 'Compiled';
598
+ status.className = 'status status-ok';
599
+ errorBar.classList.remove('visible');
600
+ } catch (err) {
601
+ status.textContent = 'Error';
602
+ status.className = 'status status-err';
603
+ errorBar.textContent = err.message;
604
+ errorBar.classList.add('visible');
605
+ }
606
+ }
607
+
608
+ // ── Auto-compile on input ──
609
+ editor.addEventListener('input', () => {
610
+ clearTimeout(compileTimer);
611
+ compileTimer = setTimeout(compileAndRender, 200);
612
+ });
613
+
614
+ // ── Tab key support ──
615
+ editor.addEventListener('keydown', (e) => {
616
+ if (e.key === 'Tab') {
617
+ e.preventDefault();
618
+ const start = editor.selectionStart;
619
+ const end = editor.selectionEnd;
620
+ editor.value = editor.value.substring(0, start) + ' ' + editor.value.substring(end);
621
+ editor.selectionStart = editor.selectionEnd = start + 4;
622
+ compileAndRender();
623
+ }
624
+ });
625
+
626
+ // ── Theme select ──
627
+ themeSelect.addEventListener('change', compileAndRender);
628
+
629
+ // ── Copy HTML ──
630
+ copyBtn.addEventListener('click', () => {
631
+ if (lastHtml) {
632
+ navigator.clipboard.writeText(lastHtml).then(() => {
633
+ copyBtn.textContent = 'Copied!';
634
+ setTimeout(() => copyBtn.textContent = 'Copy HTML', 1500);
635
+ });
636
+ }
637
+ });
638
+
639
+ // ── Download HTML ──
640
+ downloadBtn.addEventListener('click', () => {
641
+ if (!lastHtml) return;
642
+ const blob = new Blob([lastHtml], { type: 'text/html' });
643
+ const url = URL.createObjectURL(blob);
644
+ const a = document.createElement('a');
645
+ a.href = url;
646
+ a.download = 'clou-website.html';
647
+ a.click();
648
+ URL.revokeObjectURL(url);
649
+ });
650
+
651
+ // ── Resize Handle ──
652
+ const resizeHandle = document.getElementById('resizeHandle');
653
+ const editorPanel = document.getElementById('editorPanel');
654
+ let isResizing = false;
655
+
656
+ resizeHandle.addEventListener('mousedown', (e) => {
657
+ isResizing = true;
658
+ document.body.style.cursor = 'col-resize';
659
+ document.body.style.userSelect = 'none';
660
+ });
661
+
662
+ document.addEventListener('mousemove', (e) => {
663
+ if (!isResizing) return;
664
+ const percent = (e.clientX / window.innerWidth) * 100;
665
+ if (percent > 20 && percent < 80) {
666
+ editorPanel.style.width = percent + '%';
667
+ }
668
+ });
669
+
670
+ document.addEventListener('mouseup', () => {
671
+ isResizing = false;
672
+ document.body.style.cursor = '';
673
+ document.body.style.userSelect = '';
674
+ });
675
+
676
+ // ── Load first example ──
677
+ editor.value = examples['Hello World'];
678
+ compileAndRender();
679
+ })();
680
+ </script>
681
+ </body>
682
+ </html>