papagaio 0.7.0 → 0.7.3

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/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.3",
4
4
  "description": "easy yet powerful preprocessor",
5
5
  "main": "src/papagaio.js",
6
6
  "type": "module",
package/src/louro.js ADDED
@@ -0,0 +1,235 @@
1
+ // louro - https://github.com/jardimdanificado/papagaio
2
+ function parsePattern(symbols, pat) {
3
+ const t = [], S = symbols.sigil, O = symbols.open, C = symbols.close;
4
+ let i = 0;
5
+ while (i < pat.length) {
6
+ if (pat[i] === S) {
7
+ let j = i + S.length;
8
+ const isDouble = pat[j] === S;
9
+ if (isDouble) j++;
10
+ if (pat[j] === O) {
11
+ const [od, e1] = extractBlock(symbols, pat, j);
12
+ if (pat[e1] === O) {
13
+ const [cd, e2] = extractBlock(symbols, pat, e1);
14
+ let v = '', k = e2;
15
+ while (k < pat.length && /[A-Za-z0-9_]/.test(pat[k])) v += pat[k++];
16
+ if (v) {
17
+ let optional = pat[k] === '?';
18
+ if (optional) k++;
19
+
20
+ t.push({
21
+ type: isDouble ? 'blockseq' : 'block',
22
+ varName: v,
23
+ open: unescapeDelim(od.trim()) || O,
24
+ close: unescapeDelim(cd.trim()) || C,
25
+ optional
26
+ });
27
+ i = k; continue;
28
+ }
29
+ }
30
+ }
31
+ j = i + S.length;
32
+ let v = '';
33
+ while (j < pat.length && /[A-Za-z0-9_]/.test(pat[j])) v += pat[j++];
34
+ if (v) {
35
+ const optional = pat[j] === '?';
36
+ if (optional) j++;
37
+ t.push({ type: 'var', varName: v, optional });
38
+ i = j; continue;
39
+ }
40
+ t.push({ type: 'lit', value: S }); i += S.length; continue;
41
+ }
42
+ if (/\s/.test(pat[i])) {
43
+ while (i < pat.length && /\s/.test(pat[i])) i++;
44
+ t.push({ type: 'ws' }); continue;
45
+ }
46
+ let lit = '';
47
+ while (i < pat.length && pat[i] !== S && !/\s/.test(pat[i])) lit += pat[i++];
48
+ if (lit) t.push({ type: 'lit', value: lit });
49
+ }
50
+ return t;
51
+ }
52
+
53
+ function matchPattern(symbols, src, tok, pos = 0) {
54
+ let cap = {};
55
+ const startPos = pos;
56
+
57
+ for (let ti = 0; ti < tok.length; ti++) {
58
+ const t = tok[ti];
59
+ if (t.type === 'ws') { while (pos < src.length && /\s/.test(src[pos])) pos++; continue; }
60
+ if (t.type === 'lit') { if (!src.startsWith(t.value, pos)) return null; pos += t.value.length; continue; }
61
+ if (t.type === 'var') {
62
+ while (pos < src.length && /\s/.test(src[pos])) pos++;
63
+ const nx = findNext(tok, ti);
64
+ let v = '';
65
+ if (nx && (nx.type === 'block' || nx.type === 'lit')) {
66
+ const stop = nx.type === 'block' ? nx.open : nx.value;
67
+ while (pos < src.length && !src.startsWith(stop, pos) && src[pos] !== '\n') v += src[pos++];
68
+ v = v.trimEnd();
69
+ } else {
70
+ while (pos < src.length && !/\s/.test(src[pos])) v += src[pos++];
71
+ }
72
+ if (!v && !t.optional) return null;
73
+ cap[t.varName] = v;
74
+ continue;
75
+ }
76
+ if (t.type === 'blockseq') {
77
+ let blocks = [];
78
+ while (pos < src.length && src.startsWith(t.open, pos)) {
79
+ const [c, e] = extractBlock(symbols, src, pos, t.open, t.close);
80
+ blocks.push(c);
81
+ pos = e;
82
+ while (pos < src.length && /\s/.test(src[pos])) pos++;
83
+ }
84
+ if (!blocks.length && !t.optional) return null;
85
+ cap[t.varName] = blocks;
86
+ continue;
87
+ }
88
+ if (t.type === 'block') {
89
+ if (!src.startsWith(t.open, pos)) {
90
+ if (t.optional) {
91
+ cap[t.varName] = '';
92
+ continue;
93
+ }
94
+ return null;
95
+ }
96
+
97
+ const [c, e] = extractBlock(symbols, src, pos, t.open, t.close);
98
+ cap[t.varName] = c; pos = e; continue;
99
+ }
100
+ }
101
+ return { captures: cap, startPos, endPos: pos, matched: src.slice(startPos, pos) };
102
+ }
103
+
104
+ function findNext(t, i) {
105
+ for (let k = i + 1; k < t.length; k++)
106
+ if (t[k].type !== 'ws') return t[k];
107
+ return null;
108
+ }
109
+
110
+ function extractBlock(symbols, src, i, od = symbols.open, cd = symbols.close) {
111
+ if (od.length > 1 || cd.length > 1) {
112
+ if (src.substring(i, i + od.length) === od) {
113
+ i += od.length; const s = i; let d = 0;
114
+ while (i < src.length) {
115
+ if (src.substring(i, i + od.length) === od) { d++; i += od.length; }
116
+ else if (src.substring(i, i + cd.length) === cd) {
117
+ if (!d) return [src.substring(s, i), i + cd.length];
118
+ d--; i += cd.length;
119
+ } else i++;
120
+ }
121
+ return [src.substring(s), src.length];
122
+ }
123
+ }
124
+ if (src[i] === od) {
125
+ i++; const s = i;
126
+ if (od === cd) { while (i < src.length && src[i] !== cd) i++; return [src.substring(s, i), i + 1]; }
127
+ let d = 1;
128
+ while (i < src.length && d > 0) { if (src[i] === od) d++; else if (src[i] === cd) d--; if (d > 0) i++; }
129
+ return [src.substring(s, i), i + 1];
130
+ }
131
+ return ['', i];
132
+ }
133
+
134
+ function esc(s) { return s.replace(/[.*+?^${}()|[\]\\""']/g, '\\$&'); }
135
+ function unescapeDelim(s) {
136
+ let r = '';
137
+ for (let i = 0; i < s.length; i++) {
138
+ if (s[i] === '\\' && i + 1 < s.length && (s[i + 1] === '"' || s[i + 1] === "'" || s[i + 1] === '\\')) { r += s[i + 1]; i++; }
139
+ else r += s[i];
140
+ }
141
+ return r;
142
+ }
143
+
144
+ export function capture(content, pattern, symbols = { sigil: '$', open: '{', close: '}' }) {
145
+ const tokens = parsePattern(symbols, pattern);
146
+ const matches = [];
147
+
148
+ let pos = 0;
149
+ while (pos < content.length) {
150
+ const m = matchPattern(symbols, content, tokens, pos);
151
+ if (m) {
152
+ matches.push({
153
+ matched: m.matched,
154
+ captures: m.captures,
155
+ start: m.startPos,
156
+ end: m.endPos,
157
+ index: matches.length
158
+ });
159
+ pos = m.endPos;
160
+ } else {
161
+ pos++;
162
+ }
163
+ }
164
+
165
+ return {
166
+ content,
167
+ pattern,
168
+ matches,
169
+ count: matches.length,
170
+
171
+ replace(replacement) {
172
+ if (matches.length === 0) return { content, matches: [], count: 0 };
173
+
174
+ let result = '';
175
+ let lastPos = 0;
176
+
177
+ for (const match of matches) {
178
+ result += content.slice(lastPos, match.start);
179
+
180
+ let rep = typeof replacement === 'function'
181
+ ? replacement(match)
182
+ : replacement;
183
+
184
+ for (const [key, value] of Object.entries(match.captures)) {
185
+ const varPattern = new RegExp(esc(symbols.sigil + key) + '(?![A-Za-z0-9_])', 'g');
186
+ rep = rep.replace(varPattern, value);
187
+ }
188
+
189
+ result += rep;
190
+ lastPos = match.end;
191
+ }
192
+
193
+ result += content.slice(lastPos);
194
+
195
+ return result;
196
+ },
197
+
198
+ filter(predicate) {
199
+ const filtered = matches.filter(predicate);
200
+ return {
201
+ content,
202
+ pattern,
203
+ matches: filtered,
204
+ count: filtered.length,
205
+ replace: this.replace.bind({ ...this, matches: filtered }),
206
+ filter: this.filter,
207
+ only: this.only
208
+ };
209
+ },
210
+
211
+ only(n) {
212
+ const len = this.matches.length;
213
+ let idx = n >= 0 ? n : len + n;
214
+ if (idx < 0 || idx >= len) {
215
+ return {
216
+ ...this,
217
+ matches: []
218
+ };
219
+ }
220
+ return {
221
+ ...this,
222
+ matches: [this.matches[idx]]
223
+ };
224
+ }
225
+ };
226
+ }
227
+
228
+ Object.defineProperty(String.prototype, "capture", {
229
+ value: function (pattern, symbols) {
230
+ return capture(this.toString(), pattern, symbols);
231
+ },
232
+ writable: true,
233
+ configurable: true,
234
+ enumerable: false
235
+ });
package/src/papagaio.js CHANGED
@@ -1,112 +1,5 @@
1
1
  // papagaio - https://github.com/jardimdanificado/papagaio
2
- function parsePattern(p, pat) {
3
- const t = [], S = p.symbols.sigil, O = p.symbols.open, C = p.symbols.close;
4
- let i = 0;
5
- while (i < pat.length) {
6
- if (pat.startsWith(S + p.symbols.regex, i)) {
7
- let j = i + S.length + p.symbols.regex.length;
8
- while (j < pat.length && /\s/.test(pat[j])) j++;
9
- let v = '';
10
- while (j < pat.length && /[A-Za-z0-9_]/.test(pat[j])) v += pat[j++];
11
- if (v) {
12
- while (j < pat.length && /\s/.test(pat[j])) j++;
13
- if (pat[j] === O) {
14
- const [rx, e] = extractBlock(p, pat, j);
15
- t.push({ type: 'regex', varName: v, regex: rx.trim() });
16
- i = e; continue;
17
- }
18
- }
19
- }
20
- if (pat[i] === S) {
21
- let j = i + S.length;
22
- const isDouble = pat[j] === S;
23
- if (isDouble) j++;
24
- if (pat[j] === O) {
25
- const [od, e1] = extractBlock(p, pat, j);
26
- if (pat[e1] === O) {
27
- const [cd, e2] = extractBlock(p, pat, e1);
28
- let v = '', k = e2;
29
- while (k < pat.length && /[A-Za-z0-9_]/.test(pat[k])) v += pat[k++];
30
- if (v) {
31
- t.push({ type: isDouble ? 'blockseq' : 'block', varName: v, open: unescapeDelim(od.trim()) || O, close: unescapeDelim(cd.trim()) || C });
32
- i = k; continue;
33
- }
34
- }
35
- }
36
- j = i + S.length;
37
- let v = '';
38
- while (j < pat.length && /[A-Za-z0-9_]/.test(pat[j])) v += pat[j++];
39
- if (v) {
40
- const optional = pat[j] === '?';
41
- if (optional) j++;
42
- t.push({ type: 'var', varName: v, optional });
43
- i = j; continue;
44
- }
45
- t.push({ type: 'lit', value: S }); i += S.length; continue;
46
- }
47
- if (/\s/.test(pat[i])) {
48
- while (i < pat.length && /\s/.test(pat[i])) i++;
49
- t.push({ type: 'ws' }); continue;
50
- }
51
- let lit = '';
52
- while (i < pat.length && pat[i] !== S && !/\s/.test(pat[i])) lit += pat[i++];
53
- if (lit) t.push({ type: 'lit', value: lit });
54
- }
55
- return t;
56
- }
57
-
58
- function matchPattern(p, src, tok, pos = 0) {
59
- let cap = {};
60
- for (let ti = 0; ti < tok.length; ti++) {
61
- const t = tok[ti];
62
- if (t.type === 'ws') { while (pos < src.length && /\s/.test(src[pos])) pos++; continue; }
63
- if (t.type === 'lit') { if (!src.startsWith(t.value, pos)) return null; pos += t.value.length; continue; }
64
- if (t.type === 'regex') {
65
- try {
66
- const rx = new RegExp(t.regex), m = src.slice(pos).match(rx);
67
- if (!m || m.index !== 0) return null;
68
- cap[p.symbols.sigil + t.varName] = m[0];
69
- pos += m[0].length;
70
- } catch (e) { return null; }
71
- continue;
72
- }
73
- if (t.type === 'var') {
74
- while (pos < src.length && /\s/.test(src[pos])) pos++;
75
- const nx = findNext(tok, ti);
76
- let v = '';
77
- if (nx && (nx.type === 'block' || nx.type === 'lit')) {
78
- const stop = nx.type === 'block' ? nx.open : nx.value;
79
- while (pos < src.length && !src.startsWith(stop, pos) && src[pos] !== '\n') v += src[pos++];
80
- v = v.trimEnd();
81
- } else {
82
- while (pos < src.length && !/\s/.test(src[pos])) v += src[pos++];
83
- }
84
- if (!v && !t.optional) return null;
85
- cap[p.symbols.sigil + t.varName] = v;
86
- continue;
87
- }
88
- if (t.type === 'blockseq') {
89
- let blocks = [];
90
- while (pos < src.length && src.startsWith(t.open, pos)) {
91
- const [c, e] = extractBlock(p, src, pos, t.open, t.close);
92
- blocks.push(c);
93
- pos = e;
94
- while (pos < src.length && /\s/.test(src[pos])) pos++;
95
- }
96
- if (!blocks.length) return null;
97
- cap[p.symbols.sigil + t.varName] = blocks.join(' ');
98
- continue;
99
- }
100
- if (t.type === 'block') {
101
- if (!src.startsWith(t.open, pos)) return null;
102
- const [c, e] = extractBlock(p, src, pos, t.open, t.close);
103
- cap[p.symbols.sigil + t.varName] = c; pos = e; continue;
104
- }
105
- }
106
- return { captures: cap, endPos: pos };
107
- }
108
-
109
- function findNext(t, i) { for (let k = i + 1; k < t.length; k++) if (t[k].type !== 'ws') return t[k]; return null; }
2
+ import { capture } from './louro.js';
110
3
 
111
4
  function extractBlock(p, src, i, od = p.symbols.open, cd = p.symbols.close) {
112
5
  if (od.length > 1 || cd.length > 1) {
@@ -175,47 +68,111 @@ function applyEvals(p, txt, ev) {
175
68
  let r = txt;
176
69
  for (let i = ev.length - 1; i >= 0; i--) {
177
70
  const ph = `__E${i}__`;
178
- try { r = r.replace(ph, String(Function("papagaio", "ctx", `"use strict";return(function(){${ev[i].code}})();`)(p, {}))); }
71
+ try {
72
+ r = r.replace(ph, String(
73
+ Function("ctx", `"use strict";${ev[i].code}`).call(p, {})
74
+ ));
75
+ }
179
76
  catch (e) { r = r.replace(ph, "error: " + e.message); }
180
77
  }
181
78
  return r;
182
79
  }
183
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
+
184
117
  function applyPats(p, src, pats) {
185
118
  for (const pat of pats) {
186
- const tok = parsePattern(p, pat.m);
187
- let n = '', pos = 0, ok = false;
188
- while (pos < src.length) {
189
- const m = matchPattern(p, src, tok, pos);
190
- if (m) {
191
- ok = true;
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
+
192
129
  let r = pat.r;
193
130
  const [loc, cln] = extractNested(p, r);
194
131
  r = cln;
195
- Object.keys(m.captures).forEach(k => {
196
- r = r.replace(new RegExp(esc(k) + '(?![A-Za-z0-9_])', 'g'), m.captures[k]);
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]);
197
135
  });
136
+
198
137
  if (loc.length) r = applyPats(p, r, loc);
199
- p.match = src.slice(pos, m.endPos);
138
+ p.match = match.matched;
200
139
  const [ev, ct] = extractEvals(p, r);
201
140
  if (ev.length) r = applyEvals(p, ct, ev);
202
- n += r; pos = m.endPos;
203
- } else { n += src[pos]; pos++; }
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 = capture(src, 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
+ }
204
170
  }
205
- if (ok) src = n;
206
171
  }
207
172
  return src;
208
173
  }
209
174
 
210
175
  function esc(s) { return s.replace(/[.*+?^${}()|[\]\\""']/g, '\\$&'); }
211
- function unescapeDelim(s) {
212
- let r = '';
213
- for (let i = 0; i < s.length; i++) {
214
- if (s[i] === '\\' && i + 1 < s.length && (s[i+1] === '"' || s[i+1] === "'" || s[i+1] === '\\')) { r += s[i+1]; i++; }
215
- else r += s[i];
216
- }
217
- return r;
218
- }
219
176
 
220
177
  export class Papagaio {
221
178
  constructor(sigil = '$', open = '{', close = '}', pattern = 'pattern', evalKw = 'eval', blockKw = 'recursive', regexKw = 'regex', blockseqKw = 'sequential') {