papagaio 0.7.1 → 0.7.5
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 +1 -1
- package/bin/cli.mjs +114 -130
- package/index.html +160 -282
- package/package.json +2 -2
- package/papagaio.js +202 -0
- package/tests/test.js +1 -1
- package/examples/simple.html +0 -15
- package/examples/wasm.papagaio +0 -70
- package/mobile.html +0 -209
- package/src/papagaio-bootstrap.mjs +0 -23
- package/src/papagaio.js +0 -249
package/papagaio.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// papagaio - https://github.com/jardimdanificado/papagaio
|
|
2
|
+
import 'https://unpkg.com/louro@latest/louro.js';
|
|
3
|
+
|
|
4
|
+
function extractBlock(p, src, i, od = p.symbols.open, cd = p.symbols.close) {
|
|
5
|
+
if (od.length > 1 || cd.length > 1) {
|
|
6
|
+
if (src.substring(i, i + od.length) === od) {
|
|
7
|
+
i += od.length; const s = i; let d = 0;
|
|
8
|
+
while (i < src.length) {
|
|
9
|
+
if (src.substring(i, i + od.length) === od) { d++; i += od.length; }
|
|
10
|
+
else if (src.substring(i, i + cd.length) === cd) {
|
|
11
|
+
if (!d) return [src.substring(s, i), i + cd.length];
|
|
12
|
+
d--; i += cd.length;
|
|
13
|
+
} else i++;
|
|
14
|
+
}
|
|
15
|
+
return [src.substring(s), src.length];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (src[i] === od) {
|
|
19
|
+
i++; const s = i;
|
|
20
|
+
if (od === cd) { while (i < src.length && src[i] !== cd) i++; return [src.substring(s, i), i + 1]; }
|
|
21
|
+
let d = 1;
|
|
22
|
+
while (i < src.length && d > 0) { if (src[i] === od) d++; else if (src[i] === cd) d--; if (d > 0) i++; }
|
|
23
|
+
return [src.substring(s, i), i + 1];
|
|
24
|
+
}
|
|
25
|
+
return ['', i];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function extractNested(p, txt) {
|
|
29
|
+
const loc = [], S = p.symbols.sigil, O = p.symbols.open;
|
|
30
|
+
let out = txt;
|
|
31
|
+
const rx = new RegExp(`${esc(S)}${esc(p.symbols.pattern)}\\s*${esc(O)}`, "g");
|
|
32
|
+
while (1) {
|
|
33
|
+
rx.lastIndex = 0; const m = rx.exec(out); if (!m) break;
|
|
34
|
+
const s = m.index, o = m.index + m[0].length - O.length;
|
|
35
|
+
const [mp, em] = extractBlock(p, out, o); let k = em;
|
|
36
|
+
while (k < out.length && /\s/.test(out[k])) k++;
|
|
37
|
+
if (k < out.length && out.substring(k, k + O.length) === O) {
|
|
38
|
+
const [rp, er] = extractBlock(p, out, k);
|
|
39
|
+
loc.push({ m: mp.trim(), r: rp.trim() });
|
|
40
|
+
out = out.slice(0, s) + out.slice(er); continue;
|
|
41
|
+
}
|
|
42
|
+
out = out.slice(0, s) + out.slice(em);
|
|
43
|
+
}
|
|
44
|
+
return [loc, out];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function extractEvals(p, txt) {
|
|
48
|
+
const ev = [], S = p.symbols.sigil, O = p.symbols.open;
|
|
49
|
+
let i = 0, out = txt, off = 0;
|
|
50
|
+
while (i < txt.length) {
|
|
51
|
+
if (txt.substring(i, i + S.length) === S && txt.substring(i + S.length).startsWith(p.symbols.eval)) {
|
|
52
|
+
let j = i + S.length + p.symbols.eval.length;
|
|
53
|
+
while (j < txt.length && /\s/.test(txt[j])) j++;
|
|
54
|
+
if (j < txt.length && txt.substring(j, j + O.length) === O) {
|
|
55
|
+
const sp = i, bp = j, [c, ep] = extractBlock(p, txt, bp);
|
|
56
|
+
ev.push({ code: c, sp: sp - off, ep: ep - off });
|
|
57
|
+
const ph = `__E${ev.length - 1}__`;
|
|
58
|
+
out = out.substring(0, sp - off) + ph + out.substring(ep - off);
|
|
59
|
+
off += (ep - sp) - ph.length; i = ep; continue;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
i++;
|
|
63
|
+
}
|
|
64
|
+
return [ev, out];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function applyEvals(p, txt, ev) {
|
|
68
|
+
let r = txt;
|
|
69
|
+
for (let i = ev.length - 1; i >= 0; i--) {
|
|
70
|
+
const ph = `__E${i}__`;
|
|
71
|
+
try {
|
|
72
|
+
r = r.replace(ph, String(
|
|
73
|
+
Function("ctx", `"use strict";${ev[i].code}`).call(p, {})
|
|
74
|
+
));
|
|
75
|
+
}
|
|
76
|
+
catch (e) { r = r.replace(ph, "error: " + e.message); }
|
|
77
|
+
}
|
|
78
|
+
return r;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function processRegexPatterns(p, src, pattern) {
|
|
82
|
+
// Processa padrões regex que o louro não suporta nativamente
|
|
83
|
+
const S = p.symbols.sigil, O = p.symbols.open;
|
|
84
|
+
const regexMatch = pattern.match(new RegExp(`${esc(S)}${esc(p.symbols.regex)}\\s+([A-Za-z0-9_]+)\\s*${esc(O)}([^${esc(p.symbols.close)}]*)${esc(p.symbols.close)}`));
|
|
85
|
+
|
|
86
|
+
if (!regexMatch) return null;
|
|
87
|
+
|
|
88
|
+
const varName = regexMatch[1];
|
|
89
|
+
const regexStr = regexMatch[2].trim();
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
const rx = new RegExp(regexStr);
|
|
93
|
+
const matches = [];
|
|
94
|
+
let pos = 0;
|
|
95
|
+
|
|
96
|
+
while (pos < src.length) {
|
|
97
|
+
const m = src.slice(pos).match(rx);
|
|
98
|
+
if (m && m.index === 0) {
|
|
99
|
+
matches.push({
|
|
100
|
+
matched: m[0],
|
|
101
|
+
captures: { [varName]: m[0] },
|
|
102
|
+
start: pos,
|
|
103
|
+
end: pos + m[0].length
|
|
104
|
+
});
|
|
105
|
+
pos += m[0].length;
|
|
106
|
+
} else {
|
|
107
|
+
pos++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return matches;
|
|
112
|
+
} catch (e) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function applyPats(p, src, pats) {
|
|
118
|
+
for (const pat of pats) {
|
|
119
|
+
// Verifica se é um padrão regex
|
|
120
|
+
const regexMatches = processRegexPatterns(p, src, pat.m);
|
|
121
|
+
|
|
122
|
+
if (regexMatches) {
|
|
123
|
+
// Processa como padrão regex
|
|
124
|
+
let n = '', lastPos = 0;
|
|
125
|
+
|
|
126
|
+
for (const match of regexMatches) {
|
|
127
|
+
n += src.slice(lastPos, match.start);
|
|
128
|
+
|
|
129
|
+
let r = pat.r;
|
|
130
|
+
const [loc, cln] = extractNested(p, r);
|
|
131
|
+
r = cln;
|
|
132
|
+
|
|
133
|
+
Object.keys(match.captures).forEach(k => {
|
|
134
|
+
r = r.replace(new RegExp(esc(p.symbols.sigil + k) + '(?![A-Za-z0-9_])', 'g'), match.captures[k]);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (loc.length) r = applyPats(p, r, loc);
|
|
138
|
+
p.match = match.matched;
|
|
139
|
+
const [ev, ct] = extractEvals(p, r);
|
|
140
|
+
if (ev.length) r = applyEvals(p, ct, ev);
|
|
141
|
+
|
|
142
|
+
n += r;
|
|
143
|
+
lastPos = match.end;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
n += src.slice(lastPos);
|
|
147
|
+
if (regexMatches.length > 0) src = n;
|
|
148
|
+
} else {
|
|
149
|
+
// Usa louro para padrões normais
|
|
150
|
+
const result = src.capture(pat.m, p.symbols);
|
|
151
|
+
|
|
152
|
+
if (result.count > 0) {
|
|
153
|
+
src = result.replace((match) => {
|
|
154
|
+
let r = pat.r;
|
|
155
|
+
const [loc, cln] = extractNested(p, r);
|
|
156
|
+
r = cln;
|
|
157
|
+
|
|
158
|
+
Object.keys(match.captures).forEach(k => {
|
|
159
|
+
r = r.replace(new RegExp(esc(p.symbols.sigil + k) + '(?![A-Za-z0-9_])', 'g'), match.captures[k]);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
if (loc.length) r = applyPats(p, r, loc);
|
|
163
|
+
p.match = match.matched;
|
|
164
|
+
const [ev, ct] = extractEvals(p, r);
|
|
165
|
+
if (ev.length) r = applyEvals(p, ct, ev);
|
|
166
|
+
|
|
167
|
+
return r;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return src;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function esc(s) { return s.replace(/[.*+?^${}()|[\]\\""']/g, '\\$&'); }
|
|
176
|
+
|
|
177
|
+
export default class Papagaio {
|
|
178
|
+
constructor(sigil = '$', open = '{', close = '}', pattern = 'pattern', evalKw = 'eval', blockKw = 'recursive', regexKw = 'regex', blockseqKw = 'sequential') {
|
|
179
|
+
this.symbols = { pattern, open, close, sigil, eval: evalKw, block: blockKw, regex: regexKw, blockseq: blockseqKw };
|
|
180
|
+
this.content = "";
|
|
181
|
+
this.match = "";
|
|
182
|
+
}
|
|
183
|
+
process(input) {
|
|
184
|
+
const [loc, cln] = extractNested(this, input);
|
|
185
|
+
const [evals, ph] = extractEvals(this, cln);
|
|
186
|
+
let proc = applyEvals(this, ph, evals);
|
|
187
|
+
if (loc.length === 0) {
|
|
188
|
+
this.content = proc;
|
|
189
|
+
return proc;
|
|
190
|
+
}
|
|
191
|
+
let src = proc, last = null;
|
|
192
|
+
while (src !== last) {
|
|
193
|
+
last = src;
|
|
194
|
+
src = applyPats(this, src, loc);
|
|
195
|
+
const [nested] = extractNested(this, src);
|
|
196
|
+
if (nested.length === 0) break;
|
|
197
|
+
}
|
|
198
|
+
this.content = src;
|
|
199
|
+
if (typeof this.exit == "function") this.exit();
|
|
200
|
+
return this.content;
|
|
201
|
+
}
|
|
202
|
+
}
|
package/tests/test.js
CHANGED
package/examples/simple.html
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
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>papagaio test</title>
|
|
7
|
-
</head>
|
|
8
|
-
<script src="../src/papagaio-bootstrap.mjs" type="module"></script>
|
|
9
|
-
<script type="papagaio">
|
|
10
|
-
$pattern {abc} {$eval{console.log(this)} aaaaaaaaaaaaaaaaaaaaaaaaaaaa}
|
|
11
|
-
abc
|
|
12
|
-
</script>
|
|
13
|
-
<body>
|
|
14
|
-
</body>
|
|
15
|
-
</html>
|
package/examples/wasm.papagaio
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
// generic ts-like to wasm compiler
|
|
2
|
-
|
|
3
|
-
// util patterns
|
|
4
|
-
$pattern {// $comment $regex newline{[^\n]*}} {}
|
|
5
|
-
$pattern {$regex spaces{\s\s}}{ }
|
|
6
|
-
|
|
7
|
-
$eval{
|
|
8
|
-
papagaio.exit = function()
|
|
9
|
-
{
|
|
10
|
-
papagaio.content = "(module\n" + papagaio.content + "\n)";
|
|
11
|
-
papagaio.exit = null;
|
|
12
|
-
};
|
|
13
|
-
return ""
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
$pattern {export function $name ${(}{)}params:$rets ${}{}content} {
|
|
17
|
-
$pattern {parametrize}
|
|
18
|
-
{
|
|
19
|
-
$eval {
|
|
20
|
-
let str = "$params".replace("(", "").replace(")", "");
|
|
21
|
-
let params = str.split(",").map(p => p.trim()).filter(p => p);
|
|
22
|
-
let new_stuff = "";
|
|
23
|
-
for (const param of params) {
|
|
24
|
-
if (!param.includes(":")) continue; // Pula se não tem ':'
|
|
25
|
-
const [name, type] = param.split(":");
|
|
26
|
-
if (name && type) { // Verifica se ambos existem
|
|
27
|
-
new_stuff += ` (param $${name.trim()} ${type.trim()}) `;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return new_stuff;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
(func (export "$name") parametrize (result $rets)
|
|
35
|
-
$content
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
$pattern {function $name ${}{}params{(}{)}:$rets ${}{}content} {
|
|
40
|
-
$pattern {parametrize}
|
|
41
|
-
{
|
|
42
|
-
$eval {
|
|
43
|
-
let str = "$params".replace("(", "").replace(")", "");
|
|
44
|
-
let params = str.split(",").map(p => p.trim()).filter(p => p);
|
|
45
|
-
let new_stuff = "";
|
|
46
|
-
for (const param of params) {
|
|
47
|
-
if (!param.includes(":")) continue; // Pula se não tem ':'
|
|
48
|
-
const [name, type] = param.split(":");
|
|
49
|
-
if (name && type) { // Verifica se ambos existem
|
|
50
|
-
new_stuff += ` (param $${name.trim()} ${type.trim()}) `;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return new_stuff;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
(func $$name parametrize (result $rets)
|
|
58
|
-
$content
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function name(a:i32, b:i32):i64 i64
|
|
63
|
-
{
|
|
64
|
-
contentnans
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export function funcao_exportada(a:f32, b:f32, c:f32):i64 i64 i64 i64
|
|
68
|
-
{
|
|
69
|
-
fução expoortada1
|
|
70
|
-
}
|
package/mobile.html
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
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>
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// papagaio-bootstrap.js
|
|
2
|
-
// only needed if using <script type="papagaio"> in browser
|
|
3
|
-
import { Papagaio } from "./papagaio.js";
|
|
4
|
-
|
|
5
|
-
(async () => {
|
|
6
|
-
const p = new Papagaio();
|
|
7
|
-
|
|
8
|
-
const nodes = [...document.querySelectorAll('script[type="papagaio"]')];
|
|
9
|
-
|
|
10
|
-
for (const el of nodes) {
|
|
11
|
-
let src = el.textContent;
|
|
12
|
-
|
|
13
|
-
if (el.src) {
|
|
14
|
-
src = await fetch(el.src).then(r => r.text());
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const out = p.process(src);
|
|
18
|
-
|
|
19
|
-
const s = document.createElement("div");
|
|
20
|
-
s.textContent = out;
|
|
21
|
-
window.document.body.appendChild(s);
|
|
22
|
-
}
|
|
23
|
-
})();
|