clou-lang 0.3.1 → 0.3.6
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.
- package/ai/clou-ai-prompt.md +74 -9
- package/bin/clou.js +65 -8
- package/examples/hello.html +80 -2
- package/examples/themes-demo.clou +1 -1
- package/examples/themes-demo.html +76 -48
- package/package.json +1 -1
- package/playground/clou-browser.js +523 -5
- package/playground/index.html +72 -0
- package/src/errors.js +159 -29
- package/src/lexer.js +9 -0
- package/src/terminal-parser.js +9 -0
- package/src/terminal-runtime.js +15 -0
package/ai/clou-ai-prompt.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Clou Language - AI System Prompt
|
|
2
2
|
|
|
3
|
-
You are an expert in the **Clou** programming language. Clou is
|
|
3
|
+
You are an expert in the **Clou** programming language. Clou is the simplest programming language ever made — designed so even kids can build websites and terminal apps. Its motto: **"Describe it once. Run it everywhere."**
|
|
4
4
|
|
|
5
5
|
## How Clou Works
|
|
6
6
|
|
|
@@ -9,8 +9,10 @@ Clou code compiles to HTML/CSS/JS for websites, or runs directly in the terminal
|
|
|
9
9
|
**Run:** `clou mysite.clou` (auto-detects website vs terminal)
|
|
10
10
|
**Build:** `clou build mysite.clou`
|
|
11
11
|
**Dev server:** `clou dev mysite.clou`
|
|
12
|
+
**Deploy:** `clou deploy mysite.clou`
|
|
13
|
+
**Playground:** `clou playground`
|
|
12
14
|
|
|
13
|
-
## Website Mode — Full Syntax Reference
|
|
15
|
+
## Website Mode — Full Syntax Reference (30+ Elements)
|
|
14
16
|
|
|
15
17
|
```clou
|
|
16
18
|
// Variables
|
|
@@ -53,8 +55,45 @@ page "Title" at "/":
|
|
|
53
55
|
link "text" to "url" // anchor
|
|
54
56
|
line // horizontal rule
|
|
55
57
|
space 40 // vertical spacing (px)
|
|
56
|
-
|
|
57
|
-
//
|
|
58
|
+
code "let x = 1" // code block
|
|
59
|
+
audio "song.mp3" // audio player
|
|
60
|
+
|
|
61
|
+
// Forms & Input
|
|
62
|
+
form:
|
|
63
|
+
input "placeholder"
|
|
64
|
+
textarea "Write here..."
|
|
65
|
+
checkbox "I agree"
|
|
66
|
+
dropdown "Country":
|
|
67
|
+
option "Germany"
|
|
68
|
+
option "USA"
|
|
69
|
+
option "Japan"
|
|
70
|
+
slider "Volume" 0 to 100
|
|
71
|
+
submit "Send"
|
|
72
|
+
|
|
73
|
+
// Data Display
|
|
74
|
+
table:
|
|
75
|
+
heading "Name, Role, Status"
|
|
76
|
+
row:
|
|
77
|
+
text "Alex"
|
|
78
|
+
text "Developer"
|
|
79
|
+
text "Active"
|
|
80
|
+
|
|
81
|
+
progress 75 "Loading..."
|
|
82
|
+
|
|
83
|
+
// Interactive Elements
|
|
84
|
+
tabs:
|
|
85
|
+
tab "Info":
|
|
86
|
+
text "Info content"
|
|
87
|
+
tab "Settings":
|
|
88
|
+
text "Settings content"
|
|
89
|
+
|
|
90
|
+
accordion:
|
|
91
|
+
panel "Question 1":
|
|
92
|
+
text "Answer 1"
|
|
93
|
+
panel "Question 2":
|
|
94
|
+
text "Answer 2"
|
|
95
|
+
|
|
96
|
+
// Actions (inside buttons)
|
|
58
97
|
button "Click me":
|
|
59
98
|
show message "Alert text!"
|
|
60
99
|
open "modal-name"
|
|
@@ -62,8 +101,6 @@ page "Title" at "/":
|
|
|
62
101
|
toggle "element-id"
|
|
63
102
|
go to "url"
|
|
64
103
|
|
|
65
|
-
input "placeholder"
|
|
66
|
-
|
|
67
104
|
list:
|
|
68
105
|
text "Item 1"
|
|
69
106
|
text "Item 2"
|
|
@@ -142,6 +179,11 @@ app "My App":
|
|
|
142
179
|
multiply 3 by count
|
|
143
180
|
divide 2 by count
|
|
144
181
|
|
|
182
|
+
// Math operators
|
|
183
|
+
set result to 5 + 3
|
|
184
|
+
set total to 10 * 2
|
|
185
|
+
set half to 100 / 4
|
|
186
|
+
|
|
145
187
|
// Conditions
|
|
146
188
|
if name is "Alex":
|
|
147
189
|
print "Hi Alex!"
|
|
@@ -189,6 +231,7 @@ app "My App":
|
|
|
189
231
|
6. **Templates**: Use templates for any repeated pattern (cards, sections, etc.)
|
|
190
232
|
7. **Comments**: Use `//` for comments.
|
|
191
233
|
8. **Keep it simple**: Clou's power is simplicity. Don't overcomplicate.
|
|
234
|
+
9. **Use new elements**: Prefer form/table/tabs/accordion when appropriate instead of plain boxes.
|
|
192
235
|
|
|
193
236
|
## Example: Complete Website
|
|
194
237
|
|
|
@@ -207,7 +250,7 @@ page "{brand}":
|
|
|
207
250
|
|
|
208
251
|
navbar "{brand}":
|
|
209
252
|
link "Features" to "#features"
|
|
210
|
-
link "
|
|
253
|
+
link "About" to "#about"
|
|
211
254
|
|
|
212
255
|
section "hero":
|
|
213
256
|
center
|
|
@@ -232,8 +275,30 @@ page "{brand}":
|
|
|
232
275
|
use feature("🔒", "Secure", "Safe by default.")
|
|
233
276
|
use feature("🎨", "Beautiful", "Looks great.")
|
|
234
277
|
|
|
278
|
+
section "about":
|
|
279
|
+
heading "FAQ":
|
|
280
|
+
huge
|
|
281
|
+
space 20
|
|
282
|
+
accordion:
|
|
283
|
+
panel "What is {brand}?":
|
|
284
|
+
text "The simplest way to build software."
|
|
285
|
+
panel "How much does it cost?":
|
|
286
|
+
text "Free forever."
|
|
287
|
+
panel "How do I start?":
|
|
288
|
+
text "npm install -g clou-lang"
|
|
289
|
+
|
|
290
|
+
section "contact":
|
|
291
|
+
center
|
|
292
|
+
heading "Get in Touch"
|
|
293
|
+
space 20
|
|
294
|
+
form:
|
|
295
|
+
input "Your name"
|
|
296
|
+
input "Your email"
|
|
297
|
+
textarea "Your message"
|
|
298
|
+
submit "Send Message"
|
|
299
|
+
|
|
235
300
|
footer:
|
|
236
|
-
text "© 2026 {brand}"
|
|
301
|
+
text "© 2026 {brand} — Built with Clou"
|
|
237
302
|
```
|
|
238
303
|
|
|
239
|
-
When the user asks you to build something with Clou, generate clean, well-structured Clou code following these patterns.
|
|
304
|
+
When the user asks you to build something with Clou, generate clean, well-structured Clou code following these patterns. Use the new elements (form, table, tabs, accordion, progress, dropdown, checkbox, textarea, slider, audio, code) where they make sense.
|
package/bin/clou.js
CHANGED
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
const fs = require('fs');
|
|
12
12
|
const path = require('path');
|
|
13
13
|
const { buildClou } = require('../src/index');
|
|
14
|
-
const { formatError } = require('../src/errors');
|
|
14
|
+
const { formatError, formatWarnings, scanWarnings, color } = require('../src/errors');
|
|
15
15
|
|
|
16
16
|
const args = process.argv.slice(2);
|
|
17
17
|
|
|
18
18
|
function printHelp() {
|
|
19
19
|
console.log(`
|
|
20
20
|
╔═══════════════════════════════════════╗
|
|
21
|
-
║ CLOU Language v0.3
|
|
21
|
+
║ CLOU Language v0.3.5 ║
|
|
22
22
|
║ Describe it once. Run everywhere. ║
|
|
23
23
|
╚═══════════════════════════════════════╝
|
|
24
24
|
|
|
@@ -91,10 +91,16 @@ function getOutputPath(inputFile, customOutput) {
|
|
|
91
91
|
|
|
92
92
|
function openInBrowser(filePath) {
|
|
93
93
|
const absPath = path.resolve(filePath);
|
|
94
|
-
const { exec } = require('child_process');
|
|
94
|
+
const { exec, execSync } = require('child_process');
|
|
95
95
|
|
|
96
96
|
if (process.platform === 'win32') {
|
|
97
|
-
|
|
97
|
+
// Use start command - escape path for Windows cmd
|
|
98
|
+
exec(`start "" "${absPath}"`, (err) => {
|
|
99
|
+
if (err) {
|
|
100
|
+
// Fallback: use explorer
|
|
101
|
+
exec(`explorer "${absPath}"`);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
98
104
|
} else if (process.platform === 'darwin') {
|
|
99
105
|
exec(`open "${absPath}"`);
|
|
100
106
|
} else {
|
|
@@ -132,6 +138,12 @@ async function runTerminal(inputFile) {
|
|
|
132
138
|
function runFile(inputFile) {
|
|
133
139
|
const source = fs.readFileSync(inputFile, 'utf-8');
|
|
134
140
|
|
|
141
|
+
// Scan for warnings (typos, etc.)
|
|
142
|
+
const warnings = scanWarnings(source, inputFile);
|
|
143
|
+
if (warnings.length > 0) {
|
|
144
|
+
console.error(formatWarnings(warnings, source, inputFile));
|
|
145
|
+
}
|
|
146
|
+
|
|
135
147
|
// Auto-detect: terminal app or website?
|
|
136
148
|
if (isTerminalApp(source)) {
|
|
137
149
|
runTerminal(inputFile).catch(err => {
|
|
@@ -166,6 +178,13 @@ function runFile(inputFile) {
|
|
|
166
178
|
|
|
167
179
|
function buildFile(inputFile, outputFile) {
|
|
168
180
|
const source = fs.readFileSync(inputFile, 'utf-8');
|
|
181
|
+
|
|
182
|
+
// Scan for warnings (typos, etc.)
|
|
183
|
+
const warnings = scanWarnings(source, inputFile);
|
|
184
|
+
if (warnings.length > 0) {
|
|
185
|
+
console.error(formatWarnings(warnings, source, inputFile));
|
|
186
|
+
}
|
|
187
|
+
|
|
169
188
|
const basePath = path.dirname(path.resolve(inputFile));
|
|
170
189
|
const result = buildClou(source, { basePath, filename: inputFile });
|
|
171
190
|
|
|
@@ -243,10 +262,48 @@ if (args[0] === 'ai') {
|
|
|
243
262
|
}
|
|
244
263
|
|
|
245
264
|
if (args[0] === 'playground' || args[0] === 'play') {
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
265
|
+
const playgroundDir = path.resolve(__dirname, '..', 'playground');
|
|
266
|
+
const playgroundFile = path.join(playgroundDir, 'index.html');
|
|
267
|
+
|
|
268
|
+
if (!fs.existsSync(playgroundFile)) {
|
|
269
|
+
console.error(' Error: Playground files not found.');
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Start a simple HTTP server for the playground
|
|
274
|
+
const http = require('http');
|
|
275
|
+
const port = 4000;
|
|
276
|
+
|
|
277
|
+
const mimeTypes = {
|
|
278
|
+
'.html': 'text/html',
|
|
279
|
+
'.js': 'application/javascript',
|
|
280
|
+
'.css': 'text/css',
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
const server = http.createServer((req, res) => {
|
|
284
|
+
let filePath = path.join(playgroundDir, req.url === '/' ? 'index.html' : req.url);
|
|
285
|
+
const ext = path.extname(filePath);
|
|
286
|
+
const contentType = mimeTypes[ext] || 'text/plain';
|
|
287
|
+
|
|
288
|
+
fs.readFile(filePath, (err, data) => {
|
|
289
|
+
if (err) {
|
|
290
|
+
res.writeHead(404);
|
|
291
|
+
res.end('Not found');
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
res.writeHead(200, { 'Content-Type': contentType });
|
|
295
|
+
res.end(data);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
server.listen(port, () => {
|
|
300
|
+
console.log(` Clou Playground running at http://localhost:${port}`);
|
|
301
|
+
console.log(' Press Ctrl+C to stop.\n');
|
|
302
|
+
openInBrowser(`http://localhost:${port}`);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// Don't exit - keep server running
|
|
306
|
+
return;
|
|
250
307
|
}
|
|
251
308
|
|
|
252
309
|
// Handle deploy command (before smart detection)
|
package/examples/hello.html
CHANGED
|
@@ -174,6 +174,82 @@
|
|
|
174
174
|
display: inline-block;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
.clou-table {
|
|
178
|
+
width: 100%;
|
|
179
|
+
border-collapse: collapse;
|
|
180
|
+
margin: 16px 0;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.clou-table th, .clou-table td {
|
|
184
|
+
padding: 12px 16px;
|
|
185
|
+
text-align: left;
|
|
186
|
+
border-bottom: 1px solid rgba(128,128,128,0.2);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.clou-table th {
|
|
190
|
+
font-weight: 600;
|
|
191
|
+
opacity: 0.8;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.clou-table tr:hover td {
|
|
195
|
+
background: rgba(128,128,128,0.05);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.clou-form {
|
|
199
|
+
margin: 16px 0;
|
|
200
|
+
display: flex;
|
|
201
|
+
flex-direction: column;
|
|
202
|
+
gap: 12px;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.clou-checkbox {
|
|
206
|
+
display: flex;
|
|
207
|
+
align-items: center;
|
|
208
|
+
gap: 8px;
|
|
209
|
+
margin: 8px 0;
|
|
210
|
+
cursor: pointer;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.clou-checkbox input[type="checkbox"] {
|
|
214
|
+
width: 18px;
|
|
215
|
+
height: 18px;
|
|
216
|
+
cursor: pointer;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.clou-code {
|
|
220
|
+
background: rgba(0,0,0,0.3);
|
|
221
|
+
border-radius: 8px;
|
|
222
|
+
padding: 16px 20px;
|
|
223
|
+
margin: 12px 0;
|
|
224
|
+
overflow-x: auto;
|
|
225
|
+
font-family: 'Fira Code', 'Consolas', monospace;
|
|
226
|
+
font-size: 14px;
|
|
227
|
+
line-height: 1.5;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.clou-audio {
|
|
231
|
+
width: 100%;
|
|
232
|
+
max-width: 400px;
|
|
233
|
+
margin: 8px 0;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.clou-dropdown {
|
|
237
|
+
margin: 8px 0;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.clou-dropdown label {
|
|
241
|
+
display: block;
|
|
242
|
+
margin-bottom: 6px;
|
|
243
|
+
font-size: 14px;
|
|
244
|
+
opacity: 0.8;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
select.clou-input {
|
|
248
|
+
width: auto;
|
|
249
|
+
min-width: 200px;
|
|
250
|
+
cursor: pointer;
|
|
251
|
+
}
|
|
252
|
+
|
|
177
253
|
.clou-footer {
|
|
178
254
|
padding: 40px 20px;
|
|
179
255
|
margin-top: 40px;
|
|
@@ -192,11 +268,12 @@
|
|
|
192
268
|
<p>It's so easy, anyone can do it!</p>
|
|
193
269
|
</div>
|
|
194
270
|
<hr>
|
|
195
|
-
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
196
274
|
<h2>About Me</h2>
|
|
197
275
|
<p>I love coding with Clou because it's simple and fun.</p>
|
|
198
276
|
<img src="https://picsum.photos/600/300" alt="image">
|
|
199
|
-
</div>
|
|
200
277
|
<hr>
|
|
201
278
|
<div class="clou-row">
|
|
202
279
|
<button id="clou-1">Say Hello</button>
|
|
@@ -208,6 +285,7 @@
|
|
|
208
285
|
<li>Fun to use</li>
|
|
209
286
|
<li>Makes real websites</li>
|
|
210
287
|
</ul>
|
|
288
|
+
|
|
211
289
|
<script>
|
|
212
290
|
document.getElementById('clou-1').addEventListener('click', function() {
|
|
213
291
|
alert("Hello from Clou!");
|
|
@@ -172,6 +172,82 @@
|
|
|
172
172
|
display: inline-block;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
.clou-table {
|
|
176
|
+
width: 100%;
|
|
177
|
+
border-collapse: collapse;
|
|
178
|
+
margin: 16px 0;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.clou-table th, .clou-table td {
|
|
182
|
+
padding: 12px 16px;
|
|
183
|
+
text-align: left;
|
|
184
|
+
border-bottom: 1px solid rgba(128,128,128,0.2);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.clou-table th {
|
|
188
|
+
font-weight: 600;
|
|
189
|
+
opacity: 0.8;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.clou-table tr:hover td {
|
|
193
|
+
background: rgba(128,128,128,0.05);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.clou-form {
|
|
197
|
+
margin: 16px 0;
|
|
198
|
+
display: flex;
|
|
199
|
+
flex-direction: column;
|
|
200
|
+
gap: 12px;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.clou-checkbox {
|
|
204
|
+
display: flex;
|
|
205
|
+
align-items: center;
|
|
206
|
+
gap: 8px;
|
|
207
|
+
margin: 8px 0;
|
|
208
|
+
cursor: pointer;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.clou-checkbox input[type="checkbox"] {
|
|
212
|
+
width: 18px;
|
|
213
|
+
height: 18px;
|
|
214
|
+
cursor: pointer;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.clou-code {
|
|
218
|
+
background: rgba(0,0,0,0.3);
|
|
219
|
+
border-radius: 8px;
|
|
220
|
+
padding: 16px 20px;
|
|
221
|
+
margin: 12px 0;
|
|
222
|
+
overflow-x: auto;
|
|
223
|
+
font-family: 'Fira Code', 'Consolas', monospace;
|
|
224
|
+
font-size: 14px;
|
|
225
|
+
line-height: 1.5;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.clou-audio {
|
|
229
|
+
width: 100%;
|
|
230
|
+
max-width: 400px;
|
|
231
|
+
margin: 8px 0;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.clou-dropdown {
|
|
235
|
+
margin: 8px 0;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.clou-dropdown label {
|
|
239
|
+
display: block;
|
|
240
|
+
margin-bottom: 6px;
|
|
241
|
+
font-size: 14px;
|
|
242
|
+
opacity: 0.8;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
select.clou-input {
|
|
246
|
+
width: auto;
|
|
247
|
+
min-width: 200px;
|
|
248
|
+
cursor: pointer;
|
|
249
|
+
}
|
|
250
|
+
|
|
175
251
|
.clou-footer {
|
|
176
252
|
padding: 40px 20px;
|
|
177
253
|
margin-top: 40px;
|
|
@@ -231,54 +307,6 @@
|
|
|
231
307
|
}
|
|
232
308
|
.clou-animate-grow { animation: clou-grow 0.5s ease both; }
|
|
233
309
|
|
|
234
|
-
/* Theme: Ocean */
|
|
235
|
-
body {
|
|
236
|
-
background: linear-gradient(180deg, #0c1b33 0%, #1a3a5c 50%, #0c1b33 100%);
|
|
237
|
-
background-attachment: fixed;
|
|
238
|
-
color: #c8dbe6;
|
|
239
|
-
font-family: 'Georgia', 'Times New Roman', serif;
|
|
240
|
-
}
|
|
241
|
-
button, .clou-button {
|
|
242
|
-
background-color: #4fc3f7;
|
|
243
|
-
}
|
|
244
|
-
button:hover, .clou-button:hover {
|
|
245
|
-
background-color: #29b6f6;
|
|
246
|
-
}
|
|
247
|
-
.clou-card {
|
|
248
|
-
background: rgba(79, 195, 247, 0.08);
|
|
249
|
-
border: 1px solid rgba(79, 195, 247, 0.15);
|
|
250
|
-
backdrop-filter: blur(12px);
|
|
251
|
-
}
|
|
252
|
-
.clou-card:hover {
|
|
253
|
-
background: rgba(79, 195, 247, 0.12);
|
|
254
|
-
box-shadow: 0 8px 32px rgba(79, 195, 247, 0.15);
|
|
255
|
-
}
|
|
256
|
-
.clou-navbar {
|
|
257
|
-
background: rgba(12, 27, 51, 0.9);
|
|
258
|
-
backdrop-filter: blur(12px);
|
|
259
|
-
}
|
|
260
|
-
input, textarea, .clou-input {
|
|
261
|
-
background: rgba(79, 195, 247, 0.08);
|
|
262
|
-
border: 1px solid rgba(79, 195, 247, 0.25);
|
|
263
|
-
color: #c8dbe6;
|
|
264
|
-
}
|
|
265
|
-
input:focus, textarea:focus {
|
|
266
|
-
border-color: #4fc3f7;
|
|
267
|
-
box-shadow: 0 0 0 3px #4fc3f733;
|
|
268
|
-
}
|
|
269
|
-
h1, h2 {
|
|
270
|
-
color: #4fc3f7;
|
|
271
|
-
}
|
|
272
|
-
a {
|
|
273
|
-
color: #4fc3f7;
|
|
274
|
-
}
|
|
275
|
-
hr {
|
|
276
|
-
border-top-color: rgba(79, 195, 247, 0.2);
|
|
277
|
-
}
|
|
278
|
-
.clou-footer {
|
|
279
|
-
border-top-color: rgba(79, 195, 247, 0.2);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
310
|
</style>
|
|
283
311
|
</head>
|
|
284
312
|
<body>
|