@reidelsaltres/pureper 0.1.72 → 0.1.74
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PHTMLParser.d.ts","sourceRoot":"","sources":["../../src/foundation/PHTMLParser.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,OAAO,OAAO,WAAW;
|
|
1
|
+
{"version":3,"file":"PHTMLParser.d.ts","sourceRoot":"","sources":["../../src/foundation/PHTMLParser.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,OAAO,OAAO,WAAW;IAG5B,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAcnC,OAAO,CAAC,aAAa;IA4CrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAKlB;IACK,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM;IAExC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAQ/C,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG;IAWxE,OAAO,CAAC,cAAc;IAMf,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM;CAWrE"}
|
|
@@ -7,39 +7,62 @@ class PHTMLParserRule {
|
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
export default class PHTMLParser {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
// Extracts a balanced block starting from position `start` in `content`.
|
|
11
|
+
// Returns { block, end } where `block` is the content inside braces and `end` is the position after closing brace.
|
|
12
|
+
static extractBalancedBlock(content, start) {
|
|
13
|
+
if (content[start] !== '{')
|
|
14
|
+
return null;
|
|
15
|
+
let depth = 1;
|
|
16
|
+
let i = start + 1;
|
|
17
|
+
while (i < content.length && depth > 0) {
|
|
18
|
+
if (content[i] === '{')
|
|
19
|
+
depth++;
|
|
20
|
+
else if (content[i] === '}')
|
|
21
|
+
depth--;
|
|
22
|
+
i++;
|
|
23
|
+
}
|
|
24
|
+
if (depth !== 0)
|
|
25
|
+
return null;
|
|
26
|
+
return { block: content.slice(start + 1, i - 1), end: i };
|
|
27
|
+
}
|
|
28
|
+
// Parses @for constructs with proper nesting support using brace counting.
|
|
29
|
+
parseForLoops(content, scope) {
|
|
30
|
+
const forPattern = /@for\s*\(([A-Za-z0-9_$]+)\s+in\s+([A-Za-z0-9_$.]+)\s*\)\s*\{/g;
|
|
31
|
+
let result = '';
|
|
32
|
+
let lastIndex = 0;
|
|
33
|
+
let match;
|
|
34
|
+
while ((match = forPattern.exec(content)) !== null) {
|
|
35
|
+
// Append text before this @for
|
|
36
|
+
result += content.slice(lastIndex, match.index);
|
|
37
|
+
const iterVar = match[1];
|
|
38
|
+
const iterableExpr = match[2];
|
|
39
|
+
const blockStart = match.index + match[0].length - 1; // position of '{'
|
|
40
|
+
const extracted = PHTMLParser.extractBalancedBlock(content, blockStart);
|
|
41
|
+
if (!extracted) {
|
|
42
|
+
// Unbalanced braces, just append the match as-is and continue
|
|
43
|
+
result += match[0];
|
|
44
|
+
lastIndex = match.index + match[0].length;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const inner = extracted.block;
|
|
48
|
+
lastIndex = extracted.end;
|
|
49
|
+
forPattern.lastIndex = lastIndex; // Update regex position
|
|
50
|
+
const resolved = this.resolveExpression(iterableExpr, scope);
|
|
18
51
|
const arr = Array.isArray(resolved) ? resolved : [];
|
|
19
52
|
const resultParts = [];
|
|
20
|
-
let i = 0;
|
|
21
53
|
for (const item of arr) {
|
|
22
54
|
const fullScope = Object.assign({}, scope, { [iterVar]: item });
|
|
23
|
-
// parse inner block for
|
|
24
|
-
|
|
25
|
-
// normalize whitespace: remove leading/trailing whitespace lines and
|
|
26
|
-
if (i === 0) {
|
|
27
|
-
t = t.trim();
|
|
28
|
-
t = " " + t;
|
|
29
|
-
}
|
|
30
|
-
t = t.split(/\n/)
|
|
31
|
-
//.map(line => line.trim())
|
|
32
|
-
.filter(line => line.length > 0)
|
|
33
|
-
.toString();
|
|
34
|
-
//.join('\n');
|
|
55
|
+
// Recursively parse inner block (handles nested @for and other rules)
|
|
56
|
+
const t = this.parse(inner, fullScope);
|
|
35
57
|
resultParts.push(t);
|
|
36
|
-
i++;
|
|
37
58
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
59
|
+
result += resultParts.join('\n');
|
|
60
|
+
}
|
|
61
|
+
// Append remaining content after last match
|
|
62
|
+
result += content.slice(lastIndex);
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
static rules = [
|
|
43
66
|
new PHTMLParserRule(/@\(\(([\s\S]+?)\)\)/g, (parser, m, scope) => parser.stringifyValue(parser.resolveExpression(m[1], scope))),
|
|
44
67
|
new PHTMLParserRule(/@\(([\s\S]+?)\)/g, (parser, m, scope) => parser.stringifyValue(parser.resolveExpression(m[1], scope))),
|
|
45
68
|
];
|
|
@@ -67,10 +90,12 @@ export default class PHTMLParser {
|
|
|
67
90
|
return '';
|
|
68
91
|
if (typeof val === 'string')
|
|
69
92
|
return val;
|
|
70
|
-
return
|
|
93
|
+
return JSON.stringify(val);
|
|
71
94
|
}
|
|
72
95
|
parse(content, scope) {
|
|
73
|
-
|
|
96
|
+
// First, parse @for loops with proper nesting support
|
|
97
|
+
let working = this.parseForLoops(content, scope);
|
|
98
|
+
// Then apply other rules
|
|
74
99
|
for (const rule of PHTMLParser.rules) {
|
|
75
100
|
working = working.replace(rule.pattern, (...args) => rule.replacer(this, args, scope));
|
|
76
101
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PHTMLParser.js","sourceRoot":"","sources":["../../src/foundation/PHTMLParser.ts"],"names":[],"mappings":"AAAA,MAAM,eAAe;IACV,OAAO,CAAS;IAEhB,QAAQ,CAAkF;IAEjG,YAAY,OAAe,EAAE,QAAyF;QAClH,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;CACJ;AAED,MAAM,CAAC,OAAO,OAAO,WAAW;
|
|
1
|
+
{"version":3,"file":"PHTMLParser.js","sourceRoot":"","sources":["../../src/foundation/PHTMLParser.ts"],"names":[],"mappings":"AAAA,MAAM,eAAe;IACV,OAAO,CAAS;IAEhB,QAAQ,CAAkF;IAEjG,YAAY,OAAe,EAAE,QAAyF;QAClH,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;CACJ;AAED,MAAM,CAAC,OAAO,OAAO,WAAW;IAC5B,yEAAyE;IACzE,mHAAmH;IAC3G,MAAM,CAAC,oBAAoB,CAAC,OAAe,EAAE,KAAa;QAC9D,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QACxC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;QAClB,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACrC,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG;gBAAE,KAAK,EAAE,CAAC;iBAC3B,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG;gBAAE,KAAK,EAAE,CAAC;YACrC,CAAC,EAAE,CAAC;QACR,CAAC;QACD,IAAI,KAAK,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC7B,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAC9D,CAAC;IAED,2EAA2E;IACnE,aAAa,CAAC,OAAe,EAAE,KAA2B;QAC9D,MAAM,UAAU,GAAG,+DAA+D,CAAC;QACnF,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,KAA6B,CAAC;QAElC,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACjD,+BAA+B;YAC/B,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAEhD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,kBAAkB;YAExE,MAAM,SAAS,GAAG,WAAW,CAAC,oBAAoB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;YACxE,IAAI,CAAC,SAAS,EAAE,CAAC;gBACb,8DAA8D;gBAC9D,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;gBACnB,SAAS,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;gBAC1C,SAAS;YACb,CAAC;YAED,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;YAC9B,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC;YAC1B,UAAU,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC,wBAAwB;YAE1D,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;YAC7D,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YAEpD,MAAM,WAAW,GAAa,EAAE,CAAC;YACjC,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;gBACrB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;gBAChE,sEAAsE;gBACtE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;gBACvC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACxB,CAAC;YACD,MAAM,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;QAED,4CAA4C;QAC5C,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACnC,OAAO,MAAM,CAAC;IAClB,CAAC;IAEO,MAAM,CAAC,KAAK,GAAsB;QACtC,IAAI,eAAe,CAAC,sBAAsB,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,CAC7D,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACjE,IAAI,eAAe,CAAC,kBAAkB,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,CACzD,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;KACpE,CAAC;IACK,SAAS,GAA4B,EAAE,CAAC;IAExC,WAAW,CAAC,IAAY,EAAE,KAAc;QAC3C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QAC7B,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,qFAAqF;IACrF,0DAA0D;IAC1D,oGAAoG;IAC7F,iBAAiB,CAAC,IAAY,EAAE,KAA2B;QAC9D,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAChE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjE,IAAI,GAAG,GAAQ,QAAQ,CAAC;QACxB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,IAAI,GAAG,IAAI,IAAI;gBAAE,OAAO,SAAS,CAAC;YAClC,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,GAAG,CAAC;IACf,CAAC;IAEO,cAAc,CAAC,GAAQ;QAC3B,IAAI,GAAG,IAAI,IAAI;YAAE,OAAO,EAAE,CAAC;QAC3B,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC;QACxC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAEM,KAAK,CAAC,OAAe,EAAE,KAA2B;QACrD,sDAAsD;QACtD,IAAI,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAEjD,yBAAyB;QACzB,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;YACnC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAClC,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAW,EAAE,KAAK,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,OAAO,CAAC;IACnB,CAAC"}
|
package/package.json
CHANGED
|
@@ -10,43 +10,67 @@ class PHTMLParserRule {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export default class PHTMLParser {
|
|
13
|
+
// Extracts a balanced block starting from position `start` in `content`.
|
|
14
|
+
// Returns { block, end } where `block` is the content inside braces and `end` is the position after closing brace.
|
|
15
|
+
private static extractBalancedBlock(content: string, start: number): { block: string; end: number } | null {
|
|
16
|
+
if (content[start] !== '{') return null;
|
|
17
|
+
let depth = 1;
|
|
18
|
+
let i = start + 1;
|
|
19
|
+
while (i < content.length && depth > 0) {
|
|
20
|
+
if (content[i] === '{') depth++;
|
|
21
|
+
else if (content[i] === '}') depth--;
|
|
22
|
+
i++;
|
|
23
|
+
}
|
|
24
|
+
if (depth !== 0) return null;
|
|
25
|
+
return { block: content.slice(start + 1, i - 1), end: i };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Parses @for constructs with proper nesting support using brace counting.
|
|
29
|
+
private parseForLoops(content: string, scope?: Record<string, any>): string {
|
|
30
|
+
const forPattern = /@for\s*\(([A-Za-z0-9_$]+)\s+in\s+([A-Za-z0-9_$.]+)\s*\)\s*\{/g;
|
|
31
|
+
let result = '';
|
|
32
|
+
let lastIndex = 0;
|
|
33
|
+
let match: RegExpExecArray | null;
|
|
34
|
+
|
|
35
|
+
while ((match = forPattern.exec(content)) !== null) {
|
|
36
|
+
// Append text before this @for
|
|
37
|
+
result += content.slice(lastIndex, match.index);
|
|
38
|
+
|
|
39
|
+
const iterVar = match[1];
|
|
40
|
+
const iterableExpr = match[2];
|
|
41
|
+
const blockStart = match.index + match[0].length - 1; // position of '{'
|
|
42
|
+
|
|
43
|
+
const extracted = PHTMLParser.extractBalancedBlock(content, blockStart);
|
|
44
|
+
if (!extracted) {
|
|
45
|
+
// Unbalanced braces, just append the match as-is and continue
|
|
46
|
+
result += match[0];
|
|
47
|
+
lastIndex = match.index + match[0].length;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const inner = extracted.block;
|
|
52
|
+
lastIndex = extracted.end;
|
|
53
|
+
forPattern.lastIndex = lastIndex; // Update regex position
|
|
54
|
+
|
|
55
|
+
const resolved = this.resolveExpression(iterableExpr, scope);
|
|
56
|
+
const arr = Array.isArray(resolved) ? resolved : [];
|
|
57
|
+
|
|
58
|
+
const resultParts: string[] = [];
|
|
59
|
+
for (const item of arr) {
|
|
60
|
+
const fullScope = Object.assign({}, scope, { [iterVar]: item });
|
|
61
|
+
// Recursively parse inner block (handles nested @for and other rules)
|
|
62
|
+
const t = this.parse(inner, fullScope);
|
|
63
|
+
resultParts.push(t);
|
|
64
|
+
}
|
|
65
|
+
result += resultParts.join('\n');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Append remaining content after last match
|
|
69
|
+
result += content.slice(lastIndex);
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
|
|
13
73
|
private static rules: PHTMLParserRule[] = [
|
|
14
|
-
// Rule: for-loops like @for (item in items) { ... }
|
|
15
|
-
new PHTMLParserRule(/@for\s*\(([A-Za-z0-9_$]+)\s+in\s+([A-Za-z0-9_$.]+)\s*\)\s*\{([\s\S]*?)\}/g,
|
|
16
|
-
(parser, m, scope) => {
|
|
17
|
-
// m[1] = iteration variable name, m[2] = iterable expression, m[3] = inner block
|
|
18
|
-
const iterVar = m[1];
|
|
19
|
-
const iterableExpr = m[2];
|
|
20
|
-
const inner = m[3];
|
|
21
|
-
|
|
22
|
-
const resolved = parser.resolveExpression(iterableExpr, scope);
|
|
23
|
-
const arr = Array.isArray(resolved) ? resolved : [];
|
|
24
|
-
|
|
25
|
-
const resultParts: string[] = [];
|
|
26
|
-
let i = 0;
|
|
27
|
-
for (const item of arr) {
|
|
28
|
-
const fullScope = Object.assign({}, scope, { [iterVar]: item });
|
|
29
|
-
// parse inner block for this item
|
|
30
|
-
let t = parser.parse(inner, fullScope);
|
|
31
|
-
// normalize whitespace: remove leading/trailing whitespace lines and
|
|
32
|
-
if (i === 0) {
|
|
33
|
-
t = t.trim();
|
|
34
|
-
t = " " + t;
|
|
35
|
-
}
|
|
36
|
-
t = t.split(/\n/)
|
|
37
|
-
//.map(line => line.trim())
|
|
38
|
-
.filter(line => line.length > 0)
|
|
39
|
-
.toString();
|
|
40
|
-
//.join('\n');
|
|
41
|
-
resultParts.push(t);
|
|
42
|
-
i++;
|
|
43
|
-
}
|
|
44
|
-
// join each item's rendered chunk with a single newline so output is compact
|
|
45
|
-
return resultParts.join('\n');
|
|
46
|
-
|
|
47
|
-
// Parse inner block for each element in the iterable using a local scope
|
|
48
|
-
//return arr.map((el) => parser.parse(inner, Object.assign({}, scope, { [iterVar]: el }))).join('');
|
|
49
|
-
}),
|
|
50
74
|
new PHTMLParserRule(/@\(\(([\s\S]+?)\)\)/g, (parser, m, scope) =>
|
|
51
75
|
parser.stringifyValue(parser.resolveExpression(m[1], scope))),
|
|
52
76
|
new PHTMLParserRule(/@\(([\s\S]+?)\)/g, (parser, m, scope) =>
|
|
@@ -76,11 +100,14 @@ export default class PHTMLParser {
|
|
|
76
100
|
private stringifyValue(val: any): string {
|
|
77
101
|
if (val == null) return '';
|
|
78
102
|
if (typeof val === 'string') return val;
|
|
79
|
-
return
|
|
103
|
+
return JSON.stringify(val);
|
|
80
104
|
}
|
|
81
105
|
|
|
82
106
|
public parse(content: string, scope?: Record<string, any>): string {
|
|
83
|
-
|
|
107
|
+
// First, parse @for loops with proper nesting support
|
|
108
|
+
let working = this.parseForLoops(content, scope);
|
|
109
|
+
|
|
110
|
+
// Then apply other rules
|
|
84
111
|
for (const rule of PHTMLParser.rules) {
|
|
85
112
|
working = working.replace(rule.pattern,
|
|
86
113
|
(...args) => rule.replacer(this, args as any, scope));
|