papagaio 0.7.0 → 0.7.1

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.
@@ -7,7 +7,7 @@
7
7
  </head>
8
8
  <script src="../src/papagaio-bootstrap.mjs" type="module"></script>
9
9
  <script type="papagaio">
10
- $pattern {abc} {$eval{console.log(papagaio)} aaaaaaaaaaaaaaaaaaaaaaaaaaaa}
10
+ $pattern {abc} {$eval{console.log(this)} aaaaaaaaaaaaaaaaaaaaaaaaaaaa}
11
11
  abc
12
12
  </script>
13
13
  <body>
package/index.html CHANGED
@@ -2,435 +2,55 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>🦜 papagaio</title>
7
- <style>
8
- * {
9
- margin: 0;
10
- padding: 0;
11
- box-sizing: border-box;
12
- -webkit-tap-highlight-color: transparent;
13
- }
14
-
15
- body {
16
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
17
- background: #fff;
18
- color: #000;
19
- overflow-x: hidden;
20
- }
21
-
22
- .app {
23
- max-width: 100%;
24
- min-height: 100vh;
25
- display: flex;
26
- flex-direction: column;
27
- }
28
-
29
- .header {
30
- background: #fff;
31
- padding: 24px 20px;
32
- text-align: center;
33
- border-bottom: 1px solid #ddd;
34
- position: relative;
35
- cursor: pointer;
36
- user-select: none;
37
- }
38
-
39
- .header:active {
40
- background: #fafafa;
41
- }
42
-
43
- .header h1 {
44
- font-size: 2rem;
45
- color: #000;
46
- margin-bottom: 4px;
47
- }
48
-
49
- .header p {
50
- font-size: 0.9rem;
51
- color: #666;
52
- }
53
-
54
- .tabs {
55
- display: flex;
56
- background: #fff;
57
- border-bottom: 1px solid #ddd;
58
- }
59
-
60
- .tab {
61
- flex: 1;
62
- padding: 18px;
63
- text-align: center;
64
- font-size: 1rem;
65
- font-weight: 500;
66
- background: #f5f5f5;
67
- border: none;
68
- cursor: pointer;
69
- transition: all 0.2s;
70
- color: #666;
71
- border-right: 1px solid #ddd;
72
- }
73
-
74
- .tab:last-child {
75
- border-right: none;
76
- }
77
-
78
- .tab.active {
79
- background: #fff;
80
- color: #000;
81
- border-bottom: 2px solid #000;
82
- }
83
-
84
- .content {
85
- flex: 1;
86
- display: flex;
87
- flex-direction: column;
88
- overflow: hidden;
89
- padding-bottom: 130px;
90
- }
91
-
92
- .editor-container {
93
- display: none;
94
- flex-direction: column;
95
- flex: 1;
96
- }
97
-
98
- .editor-container.active {
99
- display: flex;
100
- }
101
-
102
- textarea {
103
- flex: 1;
104
- padding: 20px;
105
- border: none;
106
- font-family:
107
- ui-monospace,
108
- SFMono-Regular,
109
- Menlo,
110
- Consolas,
111
- "Liberation Mono",
112
- monospace;
113
-
114
- font-size: 15px; /* melhor que 1rem no mobile */
115
- line-height: 1.55;
116
- font-weight: 500; /* 👈 chave pra não ficar fina */
117
- letter-spacing: 0.2px;
118
-
119
- resize: none;
120
- background: #fff;
121
- color: #000;
122
-
123
- white-space: pre;
124
- overflow-x: auto;
125
- overflow-y: auto;
126
- word-break: normal;
127
- }
128
-
129
- textarea:focus {
130
- outline: none;
131
- }
132
-
133
- #output {
134
- background: #fafafa;
135
- }
136
-
137
- .action-bar {
138
- position: fixed;
139
- left: 0;
140
- right: 0;
141
- bottom: 48px;
142
- background: #fff;
143
- padding: 16px 20px;
144
- border-top: 1px solid #ddd;
145
- transition: bottom 0.15s ease-out;
146
- z-index: 100;
147
- }
148
-
149
- .process-btn {
150
- width: 100%;
151
- padding: 18px;
152
- background: #000;
153
- color: #fff;
154
- border: 1px solid #000;
155
- border-radius: 4px;
156
- font-size: 1.1rem;
157
- font-weight: 500;
158
- cursor: pointer;
159
- transition: background 0.2s;
160
- }
161
-
162
- .process-btn:active {
163
- background: #333;
164
- }
165
-
166
- input[type="file"] {
167
- display: none;
168
- }
169
-
170
- .status {
171
- position: fixed;
172
- left: 0;
173
- right: 0;
174
- bottom: 0;
175
- padding: 12px;
176
- text-align: center;
177
- font-size: 0.85rem;
178
- color: #999;
179
- background: #fff;
180
- border-top: 1px solid #ddd;
181
- transition: bottom 0.15s ease-out;
182
- z-index: 100;
183
- }
184
-
185
- .drawer-overlay {
186
- position: fixed;
187
- top: 0;
188
- left: 0;
189
- right: 0;
190
- bottom: 0;
191
- background: rgba(0,0,0,0.5);
192
- z-index: 199;
193
- display: none;
194
- }
195
-
196
- .drawer-overlay.active {
197
- display: block;
198
- }
199
-
200
- .drawer {
201
- position: fixed;
202
- top: 0;
203
- left: 0;
204
- bottom: 0;
205
- width: 85%;
206
- max-width: 400px;
207
- background: #fff;
208
- z-index: 200;
209
- transform: translateX(-100%);
210
- transition: transform 0.3s;
211
- display: flex;
212
- flex-direction: column;
213
- }
214
-
215
- .drawer.active {
216
- transform: translateX(0);
217
- }
218
-
219
- .drawer-header {
220
- padding: 24px 20px;
221
- border-bottom: 1px solid #ddd;
222
- display: flex;
223
- justify-content: space-between;
224
- align-items: center;
225
- }
226
-
227
- .drawer-header h2 {
228
- font-size: 1.3rem;
229
- font-weight: 600;
230
- }
231
-
232
- .drawer-close {
233
- width: 36px;
234
- height: 36px;
235
- border: 1px solid #ddd;
236
- border-radius: 4px;
237
- background: #fff;
238
- font-size: 1.2rem;
239
- cursor: pointer;
240
- }
241
-
242
- .drawer-close:active {
243
- background: #f5f5f5;
244
- }
245
-
246
- .drawer-content {
247
- flex: 1;
248
- overflow-y: auto;
249
- padding: 16px 20px;
250
- }
251
-
252
- .sketch-item {
253
- padding: 16px;
254
- margin-bottom: 8px;
255
- border: 1px solid #ddd;
256
- border-radius: 4px;
257
- background: #fff;
258
- cursor: pointer;
259
- transition: background 0.2s;
260
- }
261
-
262
- .sketch-item:active {
263
- background: #f5f5f5;
264
- }
265
-
266
- .sketch-item.active {
267
- background: #000;
268
- color: #fff;
269
- border-color: #000;
270
- }
271
-
272
- .sketch-item-name {
273
- font-size: 1rem;
274
- font-weight: 500;
275
- margin-bottom: 4px;
276
- }
277
-
278
- .sketch-item-date {
279
- font-size: 0.8rem;
280
- color: #999;
281
- }
282
-
283
- .sketch-item.active .sketch-item-date {
284
- color: #ccc;
285
- }
286
-
287
- .sketch-item-actions {
288
- display: flex;
289
- gap: 8px;
290
- margin-top: 12px;
291
- }
292
-
293
- .sketch-item-btn {
294
- flex: 1;
295
- padding: 8px;
296
- border: 1px solid #ddd;
297
- border-radius: 4px;
298
- background: #fff;
299
- font-size: 0.85rem;
300
- cursor: pointer;
301
- }
302
-
303
- .sketch-item.active .sketch-item-btn {
304
- border-color: #fff;
305
- color: #fff;
306
- background: transparent;
307
- }
308
-
309
- .sketch-item-btn:active {
310
- background: #f5f5f5;
311
- }
312
-
313
- .sketch-item.active .sketch-item-btn:active {
314
- background: rgba(255,255,255,0.1);
315
- }
316
-
317
- .drawer-footer {
318
- padding: 16px 20px;
319
- border-top: 1px solid #ddd;
320
- }
321
-
322
- .drawer-action-btn {
323
- width: 100%;
324
- padding: 14px;
325
- margin-bottom: 8px;
326
- background: #fff;
327
- color: #000;
328
- border: 1px solid #ddd;
329
- border-radius: 4px;
330
- font-size: 0.95rem;
331
- font-weight: 400;
332
- cursor: pointer;
333
- display: flex;
334
- align-items: center;
335
- justify-content: center;
336
- gap: 8px;
337
- }
338
-
339
- .drawer-action-btn:active {
340
- background: #f5f5f5;
341
- }
342
-
343
- .drawer-new-btn {
344
- width: 100%;
345
- padding: 16px;
346
- background: #000;
347
- color: #fff;
348
- border: none;
349
- border-radius: 4px;
350
- font-size: 1rem;
351
- font-weight: 500;
352
- cursor: pointer;
353
- margin-top: 8px;
354
- }
355
-
356
- .drawer-new-btn:active {
357
- background: #333;
358
- }
359
-
360
- .empty-state {
361
- text-align: center;
362
- padding: 40px 20px;
363
- color: #999;
364
- }
365
-
366
- @media (min-width: 768px) {
367
- .app {
368
- max-width: 600px;
369
- margin: 0 auto;
370
- border-left: 1px solid #ddd;
371
- border-right: 1px solid #ddd;
372
- }
373
-
374
- .action-bar,
375
- .status {
376
- max-width: 600px;
377
- left: 50%;
378
- transform: translateX(-50%);
379
- }
380
- }
381
- </style>
382
7
  </head>
383
8
  <body>
384
- <div class="app">
385
- <div class="header" onclick="toggleDrawer()">
386
- <h1>🦜 papagaio</h1>
387
- <p>easy yet powerful text preprocessor</p>
388
- </div>
389
-
390
- <div class="tabs">
391
- <button class="tab active" onclick="switchTab('input')">INPUT</button>
392
- <button class="tab" onclick="switchTab('output')">OUTPUT</button>
393
- </div>
394
-
395
- <div class="content">
396
- <div class="editor-container active" id="inputContainer">
397
- <textarea id="input"></textarea>
398
- </div>
399
- <div class="editor-container" id="outputContainer">
400
- <textarea id="output" readonly></textarea>
401
- </div>
402
- </div>
403
-
404
- <div class="action-bar" id="actionBar">
405
- <button class="process-btn" onclick="processCode()">Process</button>
406
- </div>
407
-
408
- <div class="status" id="statusBar">
409
- Last saved: <span id="lastSaved">never</span>
410
- </div>
411
-
412
- <div class="drawer-overlay" id="drawerOverlay" onclick="toggleDrawer()"></div>
413
- <div class="drawer" id="drawer">
414
- <div class="drawer-header">
415
- <h2 id="drawerTitle">Sketches</h2>
416
- <button class="drawer-close" onclick="toggleDrawer()">×</button>
417
- </div>
418
- <div class="drawer-content" id="drawerContent"></div>
419
- <div class="drawer-footer">
420
- <button class="drawer-action-btn" onclick="exportSketches()">
421
- ↓ Export Sketches
422
- </button>
423
- <label for="importFileInput" class="drawer-action-btn">
424
- ↑ Import Sketches
425
- </label>
426
- <input type="file" id="importFileInput" onchange="importSketches(this.files[0])" accept=".json">
427
- <button class="drawer-new-btn" onclick="createNewSketchFromDrawer()">+ New Sketch</button>
428
- </div>
429
- </div>
9
+
10
+ <h1>🦜 papagaio </h1>
11
+ <p>
12
+ easy yet powerful text preprocessor.
13
+ </p>
14
+ <hr>
15
+ <div>
16
+ <strong>
17
+ <label for="sketchSelect">Current Sketch:</label>
18
+ </strong>
19
+
20
+ <select id="sketchSelect" onchange="switchSketch()">
21
+ <option value="">-- Select Sketch --</option>
22
+ </select>
23
+ |
24
+ <button onclick="createNewSketch()">New Sketch</button>
25
+ <button onclick="renameCurrentSketch()">Rename</button>
26
+ <button onclick="deleteCurrentSketch()">Delete</button>
27
+ </div>
28
+ <hr>
29
+ <div>
30
+ <strong>
31
+ <label for="sketchSelect">Sketches:</label>
32
+ </strong>
33
+ <button onclick="exportSketches()">Export</button>
34
+ <input type="file" id="importFileInput" onchange="importSketches(this.files[0])" accept=".json">
430
35
  </div>
36
+
37
+ <hr>
38
+
39
+ <h3>INPUT</h3>
40
+ <textarea id="input" rows="15" cols="80" style="width: 70%; font-family: monospace;"></textarea>
41
+
42
+ <br><br>
43
+
44
+ <button onclick="processCode()">Process</button>
45
+
46
+ <br><br>
47
+
48
+ <h3>OUTPUT</h3>
49
+ <textarea id="output" rows="15" cols="80" style="width: 70%; font-family: monospace;" readonly></textarea>
431
50
 
432
51
  <script type="module">
433
52
  import { Papagaio } from './src/papagaio.js';
53
+
434
54
  class SketchesManager {
435
55
  constructor() {
436
56
  this.sketches = this.loadSketches();
@@ -519,86 +139,13 @@
519
139
 
520
140
  let processor = new Papagaio();
521
141
  let sketchesManager;
522
- let currentTab = 'input';
523
-
524
- function setupKeyboardAdjustment() {
525
- if (window.visualViewport) {
526
- const actionBar = document.getElementById('actionBar');
527
- const statusBar = document.getElementById('statusBar');
528
- const statusHeight = 48;
529
-
530
- window.visualViewport.addEventListener('resize', () => {
531
- const viewportHeight = window.visualViewport.height;
532
- const windowHeight = window.innerHeight;
533
- const keyboardHeight = windowHeight - viewportHeight;
534
-
535
- if (keyboardHeight > 100) {
536
- actionBar.style.bottom = `${keyboardHeight + statusHeight}px`;
537
- statusBar.style.bottom = `${keyboardHeight}px`;
538
- } else {
539
- actionBar.style.bottom = `${statusHeight}px`;
540
- statusBar.style.bottom = '0px';
541
- }
542
- });
543
-
544
- window.visualViewport.addEventListener('scroll', () => {
545
- const viewportHeight = window.visualViewport.height;
546
- const windowHeight = window.innerHeight;
547
- const keyboardHeight = windowHeight - viewportHeight;
548
-
549
- if (keyboardHeight > 100) {
550
- actionBar.style.bottom = `${keyboardHeight + statusHeight}px`;
551
- statusBar.style.bottom = `${keyboardHeight}px`;
552
- }
553
- });
554
- }
555
- }
556
142
 
557
143
  window.addEventListener('load', () => {
558
144
  sketchesManager = new SketchesManager();
559
145
  loadOrCreateDefaultSketch();
560
- renderDrawerSketches();
561
- setupSwipeGestures();
562
- setupKeyboardAdjustment();
146
+ populateSketchSelect();
563
147
  });
564
148
 
565
- function setupSwipeGestures() {
566
- let touchStartX = 0;
567
- let touchStartY = 0;
568
- let touchEndX = 0;
569
- let touchEndY = 0;
570
-
571
- document.addEventListener('touchstart', (e) => {
572
- touchStartX = e.changedTouches[0].screenX;
573
- touchStartY = e.changedTouches[0].screenY;
574
- });
575
-
576
- document.addEventListener('touchend', (e) => {
577
- touchEndX = e.changedTouches[0].screenX;
578
- touchEndY = e.changedTouches[0].screenY;
579
- handleSwipe();
580
- });
581
-
582
- function handleSwipe() {
583
- const diffX = touchEndX - touchStartX;
584
- const diffY = touchEndY - touchStartY;
585
-
586
- if (touchStartX < 50 && diffX > 100 && Math.abs(diffY) < 100) {
587
- const drawer = document.getElementById('drawer');
588
- if (!drawer.classList.contains('active')) {
589
- toggleDrawer();
590
- }
591
- }
592
-
593
- if (diffX < -100 && Math.abs(diffY) < 100) {
594
- const drawer = document.getElementById('drawer');
595
- if (drawer.classList.contains('active')) {
596
- toggleDrawer();
597
- }
598
- }
599
- }
600
- }
601
-
602
149
  function loadOrCreateDefaultSketch() {
603
150
  let sketch = null;
604
151
  if (sketchesManager.currentSketchId) {
@@ -619,45 +166,39 @@
619
166
  if (sketch) {
620
167
  document.getElementById('input').value = sketch.input;
621
168
  document.getElementById('output').value = '';
622
- updateDrawerTitle(sketch.name);
623
169
  }
624
170
  }
625
171
 
626
- function updateDrawerTitle(name) {
627
- document.getElementById('drawerTitle').textContent = `${name}`;
628
- }
629
-
630
172
  function saveCurrentSketch() {
631
173
  if (sketchesManager.currentSketchId) {
632
174
  sketchesManager.updateSketch(sketchesManager.currentSketchId, {
633
175
  input: document.getElementById('input').value
634
176
  });
635
- updateLastSaved();
636
177
  }
637
178
  }
638
179
 
639
- function updateLastSaved() {
640
- const now = new Date();
641
- const timeStr = now.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
642
- document.getElementById('lastSaved').textContent = timeStr;
180
+ function populateSketchSelect() {
181
+ const select = document.getElementById('sketchSelect');
182
+ select.innerHTML = '<option value="">-- Select Sketch --</option>';
183
+
184
+ const sketches = sketchesManager.getAllSketches();
185
+ sketches.forEach(sketch => {
186
+ const option = document.createElement('option');
187
+ option.value = sketch.id;
188
+ option.textContent = sketch.name;
189
+ if (sketch.id === sketchesManager.currentSketchId) {
190
+ option.selected = true;
191
+ }
192
+ select.appendChild(option);
193
+ });
643
194
  }
644
195
 
645
- function switchTab(tab) {
646
- currentTab = tab;
196
+ function switchSketch() {
197
+ const select = document.getElementById('sketchSelect');
198
+ const id = select.value;
647
199
 
648
- document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
649
- document.querySelectorAll('.editor-container').forEach(c => c.classList.remove('active'));
200
+ if (!id) return;
650
201
 
651
- if (tab === 'input') {
652
- document.querySelectorAll('.tab')[0].classList.add('active');
653
- document.getElementById('inputContainer').classList.add('active');
654
- } else {
655
- document.querySelectorAll('.tab')[1].classList.add('active');
656
- document.getElementById('outputContainer').classList.add('active');
657
- }
658
- }
659
-
660
- function selectSketch(id) {
661
202
  saveCurrentSketch();
662
203
  sketchesManager.setCurrentSketchId(id);
663
204
  const sketch = sketchesManager.getSketch(id);
@@ -665,83 +206,59 @@
665
206
  if (sketch) {
666
207
  document.getElementById('input').value = sketch.input;
667
208
  document.getElementById('output').value = '';
668
- updateDrawerTitle(sketch.name);
669
- renderDrawerSketches();
670
209
  }
671
210
  }
672
211
 
673
- function createNewSketchFromDrawer() {
212
+ function createNewSketch() {
674
213
  const name = prompt('Enter sketch name:');
675
214
  if (!name || !name.trim()) {
215
+ alert('Please enter a valid sketch name');
676
216
  return;
677
217
  }
678
218
 
679
219
  const id = sketchesManager.createSketch(name.trim());
220
+ populateSketchSelect();
221
+
680
222
  const sketch = sketchesManager.getSketch(id);
681
223
  if (sketch) {
682
224
  document.getElementById('input').value = sketch.input;
683
225
  document.getElementById('output').value = '';
684
- updateDrawerTitle(sketch.name);
685
- renderDrawerSketches();
686
226
  }
687
227
  }
688
228
 
689
- function renameSketchFromDrawer(id, event) {
690
- event.stopPropagation();
691
- const sketch = sketchesManager.getSketch(id);
692
- const newName = prompt('Enter new name:', sketch.name);
693
-
694
- if (!newName || !newName.trim()) {
229
+ function renameCurrentSketch() {
230
+ if (!sketchesManager.currentSketchId) {
231
+ alert('No sketch selected');
695
232
  return;
696
233
  }
697
234
 
698
- sketchesManager.renameSketch(id, newName.trim());
235
+ const sketch = sketchesManager.getSketch(sketchesManager.currentSketchId);
236
+ const newName = prompt('Enter new name:', sketch.name);
699
237
 
700
- if (id === sketchesManager.currentSketchId) {
701
- updateDrawerTitle(newName.trim());
238
+ if (!newName || !newName.trim()) {
239
+ alert('Please enter a valid name');
240
+ return;
702
241
  }
703
242
 
704
- renderDrawerSketches();
243
+ sketchesManager.renameSketch(sketchesManager.currentSketchId, newName.trim());
244
+ populateSketchSelect();
705
245
  }
706
246
 
707
- function deleteSketchFromDrawer(id, event) {
708
- event.stopPropagation();
709
- const sketch = sketchesManager.getSketch(id);
710
-
711
- if (!confirm(`Delete "${sketch.name}"?`)) {
247
+ function deleteCurrentSketch() {
248
+ if (!sketchesManager.currentSketchId) {
249
+ alert('No sketch selected');
712
250
  return;
713
251
  }
714
252
 
715
- sketchesManager.deleteSketch(id);
716
- loadOrCreateDefaultSketch();
717
- renderDrawerSketches();
718
-
719
- const currentSketch = sketchesManager.getSketch(sketchesManager.currentSketchId);
720
- if (currentSketch) {
721
- updateDrawerTitle(currentSketch.name);
722
- }
723
- }
724
-
725
- function renderDrawerSketches() {
726
- const content = document.getElementById('drawerContent');
727
- const sketches = sketchesManager.getAllSketches();
253
+ const sketch = sketchesManager.getSketch(sketchesManager.currentSketchId);
728
254
 
729
- if (sketches.length === 0) {
730
- content.innerHTML = '<div class="empty-state">No sketches yet<br>Create one to get started</div>';
255
+ if (!confirm(`Are you sure you want to delete "${sketch.name}"? This action cannot be undone.`)) {
731
256
  return;
732
257
  }
733
258
 
734
- content.innerHTML = sketches.map(sketch => `
735
- <div class="sketch-item ${sketch.id === sketchesManager.currentSketchId ? 'active' : ''}"
736
- onclick="selectSketch('${sketch.id}')">
737
- <div class="sketch-item-name">${sketch.name}</div>
738
- <div class="sketch-item-date">${sketch.createdAt}</div>
739
- <div class="sketch-item-actions">
740
- <button class="sketch-item-btn" onclick="renameSketchFromDrawer('${sketch.id}', event)">Rename</button>
741
- <button class="sketch-item-btn" onclick="deleteSketchFromDrawer('${sketch.id}', event)">Delete</button>
742
- </div>
743
- </div>
744
- `).join('');
259
+ sketchesManager.deleteSketch(sketchesManager.currentSketchId);
260
+ loadOrCreateDefaultSketch();
261
+ populateSketchSelect();
745
262
  }
746
263
 
747
264
  function processCode() {
@@ -750,25 +267,11 @@
750
267
  const output = processor.process(input);
751
268
  document.getElementById('output').value = output;
752
269
  saveCurrentSketch();
753
- switchTab('output');
754
270
  } catch (err) {
755
271
  document.getElementById('output').value = `Error: ${err.message}`;
756
272
  }
757
273
  }
758
274
 
759
- function toggleDrawer() {
760
- const drawer = document.getElementById('drawer');
761
- const overlay = document.getElementById('drawerOverlay');
762
-
763
- // Fecha o teclado ao abrir o drawer
764
- if (!drawer.classList.contains('active')) {
765
- document.activeElement?.blur();
766
- }
767
-
768
- drawer.classList.toggle('active');
769
- overlay.classList.toggle('active');
770
- }
771
-
772
275
  function exportSketches() {
773
276
  const data = {
774
277
  papagaio_sketches: localStorage.getItem('papagaio_sketches'),
@@ -805,7 +308,7 @@
805
308
  }
806
309
  location.reload();
807
310
  } catch (err) {
808
- alert('Error importing: ' + err.message);
311
+ alert('Error importing file: ' + err.message);
809
312
  }
810
313
  };
811
314
 
@@ -814,17 +317,15 @@
814
317
 
815
318
  setInterval(() => {
816
319
  saveCurrentSketch();
817
- }, 2000);
320
+ }, 1000);
818
321
 
819
322
  window.processCode = processCode;
820
- window.selectSketch = selectSketch;
821
- window.createNewSketchFromDrawer = createNewSketchFromDrawer;
822
- window.renameSketchFromDrawer = renameSketchFromDrawer;
823
- window.deleteSketchFromDrawer = deleteSketchFromDrawer;
323
+ window.switchSketch = switchSketch;
324
+ window.createNewSketch = createNewSketch;
325
+ window.renameCurrentSketch = renameCurrentSketch;
326
+ window.deleteCurrentSketch = deleteCurrentSketch;
824
327
  window.exportSketches = exportSketches;
825
328
  window.importSketches = importSketches;
826
- window.switchTab = switchTab;
827
- window.toggleDrawer = toggleDrawer;
828
329
  </script>
829
330
  </body>
830
331
  </html>
package/mobile.html ADDED
@@ -0,0 +1,209 @@
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, user-scalable=no">
6
+ <title>🦜 papagaio</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ -webkit-tap-highlight-color: transparent;
13
+ }
14
+
15
+ body {
16
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
17
+ background: #fff;
18
+ color: #000;
19
+ overflow: hidden;
20
+ }
21
+
22
+ .app {
23
+ max-width: 100%;
24
+ height: 100vh;
25
+ display: flex;
26
+ flex-direction: column;
27
+ }
28
+
29
+ .header {
30
+ background: #fff;
31
+ padding: 24px 20px;
32
+ text-align: center;
33
+ border-bottom: 1px solid #ddd;
34
+ }
35
+
36
+ .header h1 {
37
+ font-size: 2rem;
38
+ color: #000;
39
+ margin-bottom: 4px;
40
+ }
41
+
42
+ .header p {
43
+ font-size: 0.9rem;
44
+ color: #666;
45
+ }
46
+
47
+ .tabs {
48
+ display: flex;
49
+ background: #fff;
50
+ border-bottom: 1px solid #ddd;
51
+ }
52
+
53
+ .tab {
54
+ flex: 1;
55
+ padding: 18px;
56
+ text-align: center;
57
+ font-size: 1rem;
58
+ font-weight: 500;
59
+ background: #f5f5f5;
60
+ border: none;
61
+ cursor: pointer;
62
+ transition: all 0.2s;
63
+ color: #666;
64
+ border-right: 1px solid #ddd;
65
+ }
66
+
67
+ .tab:last-child {
68
+ border-right: none;
69
+ }
70
+
71
+ .tab.active {
72
+ background: #fff;
73
+ color: #000;
74
+ border-bottom: 2px solid #000;
75
+ }
76
+
77
+ .content {
78
+ flex: 1;
79
+ display: flex;
80
+ flex-direction: column;
81
+ overflow: hidden;
82
+ }
83
+
84
+ .editor-container {
85
+ display: none;
86
+ flex-direction: column;
87
+ flex: 1;
88
+ }
89
+
90
+ .editor-container.active {
91
+ display: flex;
92
+ }
93
+
94
+ textarea {
95
+ flex: 1;
96
+ padding: 20px;
97
+ border: none;
98
+ font-family:
99
+ ui-monospace,
100
+ SFMono-Regular,
101
+ Menlo,
102
+ Consolas,
103
+ "Liberation Mono",
104
+ monospace;
105
+ font-size: 15px;
106
+ line-height: 1.55;
107
+ font-weight: 500;
108
+ letter-spacing: 0.2px;
109
+ resize: none;
110
+ background: #fff;
111
+ color: #000;
112
+ white-space: pre;
113
+ overflow-x: auto;
114
+ overflow-y: auto;
115
+ word-break: normal;
116
+ }
117
+
118
+ textarea:focus {
119
+ outline: none;
120
+ }
121
+
122
+ #output {
123
+ background: #fafafa;
124
+ }
125
+
126
+ @media (min-width: 768px) {
127
+ .app {
128
+ max-width: 600px;
129
+ margin: 0 auto;
130
+ border-left: 1px solid #ddd;
131
+ border-right: 1px solid #ddd;
132
+ }
133
+ }
134
+ </style>
135
+ </head>
136
+ <body>
137
+ <div class="app">
138
+ <div class="header">
139
+ <h1>🦜 papagaio</h1>
140
+ <p>easy yet powerful text preprocessor</p>
141
+ </div>
142
+
143
+ <div class="tabs">
144
+ <button class="tab active" onclick="switchTab('input')">INPUT</button>
145
+ <button class="tab" onclick="switchTab('output')">OUTPUT</button>
146
+ </div>
147
+
148
+ <div class="content">
149
+ <div class="editor-container active" id="inputContainer">
150
+ <textarea id="input"></textarea>
151
+ </div>
152
+ <div class="editor-container" id="outputContainer">
153
+ <textarea id="output" readonly></textarea>
154
+ </div>
155
+ </div>
156
+ </div>
157
+
158
+ <script type="module">
159
+ import { Papagaio } from './src/papagaio.js';
160
+
161
+ const processor = new Papagaio();
162
+
163
+ function loadSaved() {
164
+ try {
165
+ const saved = localStorage.getItem('papagaio_input');
166
+ if (saved) {
167
+ document.getElementById('input').value = saved;
168
+ }
169
+ } catch {}
170
+ }
171
+
172
+ function saveInput() {
173
+ try {
174
+ const input = document.getElementById('input').value;
175
+ localStorage.setItem('papagaio_input', input);
176
+ } catch {}
177
+ }
178
+
179
+ function switchTab(tab) {
180
+ document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
181
+ document.querySelectorAll('.editor-container').forEach(c => c.classList.remove('active'));
182
+
183
+ if (tab === 'input') {
184
+ document.querySelectorAll('.tab')[0].classList.add('active');
185
+ document.getElementById('inputContainer').classList.add('active');
186
+ } else {
187
+ document.querySelectorAll('.tab')[1].classList.add('active');
188
+ document.getElementById('outputContainer').classList.add('active');
189
+ processCode();
190
+ }
191
+ }
192
+
193
+ function processCode() {
194
+ try {
195
+ const input = document.getElementById('input').value;
196
+ const output = processor.process(input);
197
+ document.getElementById('output').value = output;
198
+ saveInput();
199
+ } catch (err) {
200
+ document.getElementById('output').value = `Error: ${err.message}`;
201
+ }
202
+ }
203
+
204
+ window.addEventListener('load', loadSaved);
205
+ setInterval(saveInput, 2000);
206
+ window.switchTab = switchTab;
207
+ </script>
208
+ </body>
209
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "papagaio",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "easy yet powerful preprocessor",
5
5
  "main": "src/papagaio.js",
6
6
  "type": "module",
package/src/papagaio.js CHANGED
@@ -175,7 +175,11 @@ function applyEvals(p, txt, ev) {
175
175
  let r = txt;
176
176
  for (let i = ev.length - 1; i >= 0; i--) {
177
177
  const ph = `__E${i}__`;
178
- try { r = r.replace(ph, String(Function("papagaio", "ctx", `"use strict";return(function(){${ev[i].code}})();`)(p, {}))); }
178
+ try {
179
+ r = r.replace(ph, String(
180
+ Function("ctx", `"use strict";${ev[i].code}`).call(p, {})
181
+ ));
182
+ }
179
183
  catch (e) { r = r.replace(ph, "error: " + e.message); }
180
184
  }
181
185
  return r;