papagaio 0.4.2 → 0.5.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.
- package/README.md +115 -115
- package/bin/cli.qjs +57 -0
- package/index.html +278 -380
- package/package.json +1 -1
- package/src/papagaio.js +277 -464
- package/tests/tests.json +101 -605
- package/src/louro.js +0 -259
package/index.html
CHANGED
|
@@ -4,421 +4,319 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>🦜 papagaio</title>
|
|
7
|
-
<style>
|
|
8
|
-
:root {
|
|
9
|
-
--bg-dark: #282828;
|
|
10
|
-
--bg: #3c3836;
|
|
11
|
-
--bg-light: #504945;
|
|
12
|
-
--fg: #ebdbb2;
|
|
13
|
-
--fg-dark: #a89984;
|
|
14
|
-
--green: #b8bb26;
|
|
15
|
-
--yellow: #fabd2f;
|
|
16
|
-
--blue: #83a598;
|
|
17
|
-
--red: #fb4934;
|
|
18
|
-
--orange: #fe8019;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
22
|
-
|
|
23
|
-
body {
|
|
24
|
-
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
|
25
|
-
color: var(--fg);
|
|
26
|
-
padding: 15px;
|
|
27
|
-
min-height: 100vh;
|
|
28
|
-
overflow-x: hidden;
|
|
29
|
-
position: relative;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/* Animated Reggae Background Stripes */
|
|
33
|
-
body::before {
|
|
34
|
-
content: '';
|
|
35
|
-
position: fixed;
|
|
36
|
-
top: 0;
|
|
37
|
-
left: 0;
|
|
38
|
-
width: 100%;
|
|
39
|
-
height: 100%;
|
|
40
|
-
background:
|
|
41
|
-
linear-gradient(45deg,
|
|
42
|
-
#C03F31 0%, #C03F31 25%,
|
|
43
|
-
#F9DC5C 25%, #F9DC5C 50%,
|
|
44
|
-
#2D936C 50%, #2D936C 75%,
|
|
45
|
-
#0A100D 75%, #0A100D 100%);
|
|
46
|
-
background-size: 400% 400%;
|
|
47
|
-
animation: reggaeBackground 20s ease infinite;
|
|
48
|
-
z-index: -1;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@keyframes reggaeBackground {
|
|
52
|
-
0% { background-position: 0% 50%; }
|
|
53
|
-
50% { background-position: 100% 50%; }
|
|
54
|
-
100% { background-position: 0% 50%; }
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.container {
|
|
58
|
-
max-width: 1100px;
|
|
59
|
-
margin: 0 auto;
|
|
60
|
-
background: var(--bg);
|
|
61
|
-
border-radius: 8px;
|
|
62
|
-
overflow: hidden;
|
|
63
|
-
height: 95vh;
|
|
64
|
-
display: flex;
|
|
65
|
-
flex-direction: column;
|
|
66
|
-
box-shadow: 0 5px 15px rgba(0,0,0,0.5);
|
|
67
|
-
opacity: 1;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.header {
|
|
71
|
-
background: var(--bg-light);
|
|
72
|
-
padding: 12px 20px;
|
|
73
|
-
text-align: center;
|
|
74
|
-
position: relative;
|
|
75
|
-
border-bottom: 2px solid var(--yellow);
|
|
76
|
-
opacity: 1;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.header h1 {
|
|
80
|
-
font-size: 22px;
|
|
81
|
-
font-weight: bold;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.header::before, .header::after {
|
|
85
|
-
content: "🦜";
|
|
86
|
-
position: absolute;
|
|
87
|
-
top: 75%;
|
|
88
|
-
transform: translateY(-75%);
|
|
89
|
-
transition: all 0.5s ease;
|
|
90
|
-
scale: 2;
|
|
91
|
-
}
|
|
92
|
-
.header::before { left: 20px; }
|
|
93
|
-
.header::after { right: 20px; }
|
|
94
|
-
|
|
95
|
-
.animate-parrot::before,
|
|
96
|
-
.animate-parrot::after {
|
|
97
|
-
animation: parrotSpin 0.25s ease-in-out;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
@keyframes parrotSpin {
|
|
101
|
-
0% { transform: translateY(-75%) scale(1) rotate(0deg); }
|
|
102
|
-
10% { transform: translateY(-75%) scale(1.5) rotate(0deg); }
|
|
103
|
-
100% { transform: translateY(-75%) scale(1) rotate(360deg); }
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.main-controls {
|
|
107
|
-
display: flex;
|
|
108
|
-
gap: 10px;
|
|
109
|
-
padding: 12px 20px;
|
|
110
|
-
background: var(--bg-light);
|
|
111
|
-
border-bottom: 1px solid var(--bg);
|
|
112
|
-
justify-content: center;
|
|
113
|
-
flex-wrap: wrap;
|
|
114
|
-
opacity: 1;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
button {
|
|
118
|
-
padding: 8px 15px;
|
|
119
|
-
background: var(--bg);
|
|
120
|
-
color: var(--fg);
|
|
121
|
-
border: 1px solid var(--bg-light);
|
|
122
|
-
border-radius: 5px;
|
|
123
|
-
cursor: pointer;
|
|
124
|
-
font-weight: 600;
|
|
125
|
-
transition: all 0.2s;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
button:hover {
|
|
129
|
-
background: var(--yellow);
|
|
130
|
-
color: var(--bg-dark);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
.content {
|
|
134
|
-
display: flex;
|
|
135
|
-
flex: 1;
|
|
136
|
-
gap: 15px;
|
|
137
|
-
padding: 15px;
|
|
138
|
-
overflow: hidden;
|
|
139
|
-
opacity: 1;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.panel {
|
|
143
|
-
flex: 1;
|
|
144
|
-
display: flex;
|
|
145
|
-
flex-direction: column;
|
|
146
|
-
background: var(--bg-dark);
|
|
147
|
-
border-radius: 5px;
|
|
148
|
-
overflow: hidden;
|
|
149
|
-
border: 1px solid var(--bg-light);
|
|
150
|
-
opacity: 1;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
.panel h2 {
|
|
154
|
-
padding: 10px 15px;
|
|
155
|
-
background: var(--bg-light);
|
|
156
|
-
font-size: 14px;
|
|
157
|
-
text-align: center;
|
|
158
|
-
font-weight: 600;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
textarea {
|
|
162
|
-
flex: 1;
|
|
163
|
-
padding: 15px;
|
|
164
|
-
border: none;
|
|
165
|
-
background: var(--bg-dark);
|
|
166
|
-
color: var(--fg);
|
|
167
|
-
resize: none;
|
|
168
|
-
font-family: 'Monaco', 'Menlo', monospace;
|
|
169
|
-
font-size: 14px;
|
|
170
|
-
line-height: 1.5;
|
|
171
|
-
opacity: 1;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
textarea:focus {
|
|
175
|
-
outline: 2px solid var(--blue);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
.footer {
|
|
179
|
-
padding: 12px 20px;
|
|
180
|
-
background: var(--bg-light);
|
|
181
|
-
border-top: 1px solid var(--bg);
|
|
182
|
-
display: flex;
|
|
183
|
-
flex-direction: column;
|
|
184
|
-
gap: 10px;
|
|
185
|
-
position: relative;
|
|
186
|
-
opacity: 1;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
.footer::before {
|
|
190
|
-
content: "🌴🌿";
|
|
191
|
-
position: absolute;
|
|
192
|
-
bottom: 15%;
|
|
193
|
-
right: 2%;
|
|
194
|
-
opacity: 0.7;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
.footer-controls {
|
|
198
|
-
display: flex;
|
|
199
|
-
justify-content: space-between;
|
|
200
|
-
align-items: center;
|
|
201
|
-
flex-wrap: wrap;
|
|
202
|
-
gap: 10px;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
.footer-bottom {
|
|
206
|
-
display: flex;
|
|
207
|
-
justify-content: space-between;
|
|
208
|
-
align-items: center;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
.control-group {
|
|
212
|
-
display: flex;
|
|
213
|
-
align-items: center;
|
|
214
|
-
gap: 8px;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
.control-group label {
|
|
218
|
-
color: var(--fg);
|
|
219
|
-
font-size: 14px;
|
|
220
|
-
white-space: nowrap;
|
|
221
|
-
font-weight: 600;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
input[type="text"] {
|
|
225
|
-
background: var(--bg-dark);
|
|
226
|
-
border: 1px solid var(--bg-light);
|
|
227
|
-
color: var(--fg);
|
|
228
|
-
padding: 6px;
|
|
229
|
-
width: 40px;
|
|
230
|
-
text-align: center;
|
|
231
|
-
border-radius: 3px;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
.status {
|
|
235
|
-
background: var(--green);
|
|
236
|
-
color: var(--bg-dark);
|
|
237
|
-
padding: 6px 12px;
|
|
238
|
-
border-radius: 4px;
|
|
239
|
-
font-size: 14px;
|
|
240
|
-
font-weight: bold;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
.file-input { display: none; }
|
|
244
|
-
|
|
245
|
-
@media (max-width: 768px) {
|
|
246
|
-
.content { flex-direction: column; }
|
|
247
|
-
.panel { min-height: 250px; }
|
|
248
|
-
.footer-controls, .footer-bottom { flex-direction: column; align-items: stretch; gap: 10px; }
|
|
249
|
-
.control-group { justify-content: center; }
|
|
250
|
-
}
|
|
251
|
-
</style>
|
|
252
7
|
</head>
|
|
253
8
|
<body>
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
<
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
</
|
|
267
|
-
|
|
268
|
-
<
|
|
269
|
-
<div class="panel">
|
|
270
|
-
<h2>INPUT</h2>
|
|
271
|
-
<textarea id="input" placeholder="Enter your text here..."></textarea>
|
|
272
|
-
</div>
|
|
273
|
-
<div class="panel">
|
|
274
|
-
<h2>OUTPUT</h2>
|
|
275
|
-
<textarea id="output" placeholder="Output will appear here..." readonly></textarea>
|
|
276
|
-
</div>
|
|
277
|
-
</div>
|
|
278
|
-
|
|
279
|
-
<div class="footer">
|
|
280
|
-
<div class="footer-controls">
|
|
281
|
-
<div class="control-group">
|
|
282
|
-
<label>Delimiter:</label>
|
|
283
|
-
<input id="openQuote" type="text" placeholder="{">
|
|
284
|
-
<input id="closeQuote" type="text" placeholder="}">
|
|
285
|
-
<button onclick="animateParrot(); applyQuotes()">Apply</button>
|
|
286
|
-
<button onclick="animateParrot(); resetQuotes()">Reset</button>
|
|
287
|
-
</div>
|
|
288
|
-
|
|
289
|
-
<div class="control-group">
|
|
290
|
-
<label>Sigil:</label>
|
|
291
|
-
<input id="sigilInput" type="text" placeholder="$">
|
|
292
|
-
<button onclick="animateParrot(); applySigil()">Apply</button>
|
|
293
|
-
<button onclick="animateParrot(); resetSigil()">Reset</button>
|
|
294
|
-
</div>
|
|
295
|
-
</div>
|
|
296
|
-
|
|
297
|
-
<div class="footer-bottom">
|
|
298
|
-
<span id="status" class="status">READY</span>
|
|
299
|
-
</div>
|
|
300
|
-
</div>
|
|
9
|
+
|
|
10
|
+
<h1>🦜 papagaio</h1>
|
|
11
|
+
<p>
|
|
12
|
+
easy yet powerful text preprocessor.
|
|
13
|
+
</p>
|
|
14
|
+
<hr>
|
|
15
|
+
<div>
|
|
16
|
+
<label for="sketchSelect">Current Sketch:</label>
|
|
17
|
+
<select id="sketchSelect" onchange="switchSketch()">
|
|
18
|
+
<option value="">-- Select Sketch --</option>
|
|
19
|
+
</select>
|
|
20
|
+
|
|
|
21
|
+
<button onclick="createNewSketch()">New Sketch</button>
|
|
22
|
+
<button onclick="renameCurrentSketch()">Rename</button>
|
|
23
|
+
<button onclick="deleteCurrentSketch()">Delete</button>
|
|
301
24
|
</div>
|
|
25
|
+
<hr>
|
|
26
|
+
<div>
|
|
27
|
+
<label for="sketchSelect">Sketches:</label>
|
|
28
|
+
<button onclick="exportSketches()">Export</button>
|
|
29
|
+
<input type="file" id="importFileInput" onchange="importSketches(this.files[0])" accept=".json">
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<hr>
|
|
33
|
+
|
|
34
|
+
<h3>INPUT</h3>
|
|
35
|
+
<textarea id="input" rows="15" cols="80" style="width: 70%; font-family: monospace;"></textarea>
|
|
36
|
+
|
|
37
|
+
<br><br>
|
|
38
|
+
|
|
39
|
+
<button onclick="processCode()">Process</button>
|
|
40
|
+
|
|
41
|
+
<br><br>
|
|
42
|
+
|
|
43
|
+
<h3>OUTPUT</h3>
|
|
44
|
+
<textarea id="output" rows="15" cols="80" style="width: 70%; font-family: monospace;" readonly></textarea>
|
|
302
45
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
let processor = null;
|
|
46
|
+
<script type="module">
|
|
47
|
+
import { Papagaio } from './src/papagaio.js';
|
|
307
48
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
49
|
+
class SketchesManager {
|
|
50
|
+
constructor() {
|
|
51
|
+
this.sketches = this.loadSketches();
|
|
52
|
+
this.currentSketchId = this.loadCurrentSketchId();
|
|
311
53
|
}
|
|
312
54
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
55
|
+
loadSketches() {
|
|
56
|
+
try {
|
|
57
|
+
const saved = localStorage.getItem('papagaio_sketches');
|
|
58
|
+
return saved ? JSON.parse(saved) : {};
|
|
59
|
+
} catch {
|
|
60
|
+
return {};
|
|
61
|
+
}
|
|
319
62
|
}
|
|
320
63
|
|
|
321
|
-
|
|
322
|
-
|
|
64
|
+
saveSketches() {
|
|
65
|
+
try {
|
|
66
|
+
localStorage.setItem('papagaio_sketches', JSON.stringify(this.sketches));
|
|
67
|
+
} catch {}
|
|
323
68
|
}
|
|
324
69
|
|
|
325
|
-
|
|
70
|
+
loadCurrentSketchId() {
|
|
326
71
|
try {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
updateStatus('PROCESSING...');
|
|
332
|
-
const input = document.getElementById('input').value;
|
|
333
|
-
const output = processor.process(input);
|
|
334
|
-
document.getElementById('output').value = output;
|
|
335
|
-
updateStatus('COMPLETED');
|
|
336
|
-
} catch (err) {
|
|
337
|
-
document.getElementById('output').value = `Error: ${err.message}`;
|
|
338
|
-
updateStatus('ERROR');
|
|
72
|
+
return localStorage.getItem('papagaio_current_sketch');
|
|
73
|
+
} catch {
|
|
74
|
+
return null;
|
|
339
75
|
}
|
|
340
76
|
}
|
|
341
77
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
window.clearAll = clearAll;
|
|
348
|
-
window.applyQuotes = applyQuotes;
|
|
349
|
-
window.resetQuotes = resetQuotes;
|
|
350
|
-
window.applySigil = applySigil;
|
|
351
|
-
window.resetSigil = resetSigil;
|
|
352
|
-
|
|
353
|
-
function loadFile() {
|
|
354
|
-
document.getElementById('fileInput').click();
|
|
78
|
+
setCurrentSketchId(id) {
|
|
79
|
+
this.currentSketchId = id;
|
|
80
|
+
try {
|
|
81
|
+
localStorage.setItem('papagaio_current_sketch', id);
|
|
82
|
+
} catch {}
|
|
355
83
|
}
|
|
356
84
|
|
|
357
|
-
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
85
|
+
createSketch(name) {
|
|
86
|
+
const id = Date.now().toString();
|
|
87
|
+
this.sketches[id] = {
|
|
88
|
+
id,
|
|
89
|
+
name,
|
|
90
|
+
input: '',
|
|
91
|
+
createdAt: new Date().toLocaleString()
|
|
364
92
|
};
|
|
365
|
-
|
|
93
|
+
this.saveSketches();
|
|
94
|
+
this.setCurrentSketchId(id);
|
|
95
|
+
return id;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
getSketch(id) {
|
|
99
|
+
return this.sketches[id] || null;
|
|
366
100
|
}
|
|
367
101
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
102
|
+
updateSketch(id, data) {
|
|
103
|
+
if (this.sketches[id]) {
|
|
104
|
+
Object.assign(this.sketches[id], data);
|
|
105
|
+
this.saveSketches();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
deleteSketch(id) {
|
|
110
|
+
delete this.sketches[id];
|
|
111
|
+
this.saveSketches();
|
|
112
|
+
if (this.currentSketchId === id) {
|
|
113
|
+
const remaining = Object.keys(this.sketches);
|
|
114
|
+
this.currentSketchId = remaining.length > 0 ? remaining[0] : null;
|
|
115
|
+
if (this.currentSketchId) {
|
|
116
|
+
this.setCurrentSketchId(this.currentSketchId);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
getAllSketches() {
|
|
122
|
+
return Object.values(this.sketches).sort((a, b) =>
|
|
123
|
+
parseInt(b.id) - parseInt(a.id)
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
renameSketch(id, newName) {
|
|
128
|
+
if (this.sketches[id]) {
|
|
129
|
+
this.sketches[id].name = newName;
|
|
130
|
+
this.saveSketches();
|
|
131
|
+
}
|
|
379
132
|
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let processor = new Papagaio();
|
|
136
|
+
let sketchesManager;
|
|
380
137
|
|
|
381
|
-
|
|
382
|
-
|
|
138
|
+
window.addEventListener('load', () => {
|
|
139
|
+
sketchesManager = new SketchesManager();
|
|
140
|
+
loadOrCreateDefaultSketch();
|
|
141
|
+
populateSketchSelect();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
function loadOrCreateDefaultSketch() {
|
|
145
|
+
let sketch = null;
|
|
146
|
+
if (sketchesManager.currentSketchId) {
|
|
147
|
+
sketch = sketchesManager.getSketch(sketchesManager.currentSketchId);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (!sketch) {
|
|
151
|
+
const allSketches = sketchesManager.getAllSketches();
|
|
152
|
+
if (allSketches.length > 0) {
|
|
153
|
+
sketch = allSketches[0];
|
|
154
|
+
sketchesManager.setCurrentSketchId(sketch.id);
|
|
155
|
+
} else {
|
|
156
|
+
const id = sketchesManager.createSketch('Default');
|
|
157
|
+
sketch = sketchesManager.getSketch(id);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (sketch) {
|
|
162
|
+
document.getElementById('input').value = sketch.input;
|
|
383
163
|
document.getElementById('output').value = '';
|
|
384
|
-
updateStatus('CLEARED');
|
|
385
164
|
}
|
|
165
|
+
}
|
|
386
166
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
167
|
+
function saveCurrentSketch() {
|
|
168
|
+
if (sketchesManager.currentSketchId) {
|
|
169
|
+
sketchesManager.updateSketch(sketchesManager.currentSketchId, {
|
|
170
|
+
input: document.getElementById('input').value
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function populateSketchSelect() {
|
|
176
|
+
const select = document.getElementById('sketchSelect');
|
|
177
|
+
select.innerHTML = '<option value="">-- Select Sketch --</option>';
|
|
178
|
+
|
|
179
|
+
const sketches = sketchesManager.getAllSketches();
|
|
180
|
+
sketches.forEach(sketch => {
|
|
181
|
+
const option = document.createElement('option');
|
|
182
|
+
option.value = sketch.id;
|
|
183
|
+
option.textContent = sketch.name;
|
|
184
|
+
if (sketch.id === sketchesManager.currentSketchId) {
|
|
185
|
+
option.selected = true;
|
|
391
186
|
}
|
|
187
|
+
select.appendChild(option);
|
|
392
188
|
});
|
|
189
|
+
}
|
|
393
190
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
191
|
+
function switchSketch() {
|
|
192
|
+
const select = document.getElementById('sketchSelect');
|
|
193
|
+
const id = select.value;
|
|
194
|
+
|
|
195
|
+
if (!id) return;
|
|
196
|
+
|
|
197
|
+
saveCurrentSketch();
|
|
198
|
+
sketchesManager.setCurrentSketchId(id);
|
|
199
|
+
const sketch = sketchesManager.getSketch(id);
|
|
200
|
+
|
|
201
|
+
if (sketch) {
|
|
202
|
+
document.getElementById('input').value = sketch.input;
|
|
203
|
+
document.getElementById('output').value = '';
|
|
400
204
|
}
|
|
205
|
+
}
|
|
401
206
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
207
|
+
function createNewSketch() {
|
|
208
|
+
const name = prompt('Enter sketch name:');
|
|
209
|
+
if (!name || !name.trim()) {
|
|
210
|
+
alert('Please enter a valid sketch name');
|
|
211
|
+
return;
|
|
407
212
|
}
|
|
213
|
+
|
|
214
|
+
const id = sketchesManager.createSketch(name.trim());
|
|
215
|
+
populateSketchSelect();
|
|
216
|
+
|
|
217
|
+
const sketch = sketchesManager.getSketch(id);
|
|
218
|
+
if (sketch) {
|
|
219
|
+
document.getElementById('input').value = sketch.input;
|
|
220
|
+
document.getElementById('output').value = '';
|
|
221
|
+
}
|
|
222
|
+
}
|
|
408
223
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
224
|
+
function renameCurrentSketch() {
|
|
225
|
+
if (!sketchesManager.currentSketchId) {
|
|
226
|
+
alert('No sketch selected');
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const sketch = sketchesManager.getSketch(sketchesManager.currentSketchId);
|
|
231
|
+
const newName = prompt('Enter new name:', sketch.name);
|
|
232
|
+
|
|
233
|
+
if (!newName || !newName.trim()) {
|
|
234
|
+
alert('Please enter a valid name');
|
|
235
|
+
return;
|
|
414
236
|
}
|
|
237
|
+
|
|
238
|
+
sketchesManager.renameSketch(sketchesManager.currentSketchId, newName.trim());
|
|
239
|
+
populateSketchSelect();
|
|
240
|
+
}
|
|
415
241
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
242
|
+
function deleteCurrentSketch() {
|
|
243
|
+
if (!sketchesManager.currentSketchId) {
|
|
244
|
+
alert('No sketch selected');
|
|
245
|
+
return;
|
|
420
246
|
}
|
|
421
|
-
|
|
247
|
+
|
|
248
|
+
const sketch = sketchesManager.getSketch(sketchesManager.currentSketchId);
|
|
249
|
+
|
|
250
|
+
if (!confirm(`Are you sure you want to delete "${sketch.name}"? This action cannot be undone.`)) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
sketchesManager.deleteSketch(sketchesManager.currentSketchId);
|
|
255
|
+
loadOrCreateDefaultSketch();
|
|
256
|
+
populateSketchSelect();
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function processCode() {
|
|
260
|
+
try {
|
|
261
|
+
const input = document.getElementById('input').value;
|
|
262
|
+
const output = processor.process(input);
|
|
263
|
+
document.getElementById('output').value = output;
|
|
264
|
+
saveCurrentSketch();
|
|
265
|
+
} catch (err) {
|
|
266
|
+
document.getElementById('output').value = `Error: ${err.message}`;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function exportSketches() {
|
|
271
|
+
const data = {
|
|
272
|
+
papagaio_sketches: localStorage.getItem('papagaio_sketches'),
|
|
273
|
+
papagaio_current_sketch: localStorage.getItem('papagaio_current_sketch')
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const blob = new Blob([JSON.stringify(data, null, 2)], {
|
|
277
|
+
type: "application/json"
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
const a = document.createElement("a");
|
|
281
|
+
a.href = URL.createObjectURL(blob);
|
|
282
|
+
a.download = `papagaio_sketches_${Date.now()}.json`;
|
|
283
|
+
a.click();
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function importSketches(file) {
|
|
287
|
+
if (!file) return;
|
|
288
|
+
|
|
289
|
+
const reader = new FileReader();
|
|
290
|
+
|
|
291
|
+
reader.onload = () => {
|
|
292
|
+
try {
|
|
293
|
+
const data = JSON.parse(reader.result);
|
|
294
|
+
if (data.papagaio_sketches) {
|
|
295
|
+
localStorage.setItem('papagaio_sketches', data.papagaio_sketches);
|
|
296
|
+
}
|
|
297
|
+
if (data.papagaio_current_sketch) {
|
|
298
|
+
localStorage.setItem('papagaio_current_sketch', data.papagaio_current_sketch);
|
|
299
|
+
}
|
|
300
|
+
location.reload();
|
|
301
|
+
} catch (err) {
|
|
302
|
+
alert('Error importing file: ' + err.message);
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
reader.readAsText(file);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
setInterval(() => {
|
|
310
|
+
saveCurrentSketch();
|
|
311
|
+
}, 1000);
|
|
422
312
|
|
|
313
|
+
window.processCode = processCode;
|
|
314
|
+
window.switchSketch = switchSketch;
|
|
315
|
+
window.createNewSketch = createNewSketch;
|
|
316
|
+
window.renameCurrentSketch = renameCurrentSketch;
|
|
317
|
+
window.deleteCurrentSketch = deleteCurrentSketch;
|
|
318
|
+
window.exportSketches = exportSketches;
|
|
319
|
+
window.importSketches = importSketches;
|
|
320
|
+
</script>
|
|
423
321
|
</body>
|
|
424
322
|
</html>
|