@eventra_dev/eventra-cli 0.1.30 → 0.1.32
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 +0 -1
- package/dist/engine/callResolver.js +56 -25
- package/dist/engine/engine.js +7 -4
- package/dist/engine/languageService.js +36 -11
- package/dist/engine/scanner.js +224 -27
- package/dist/utils/config.js +0 -1
- package/dist/utils/processFile.js +3 -3
- package/dist/utils/universal.js +121 -53
- package/package.json +1 -1
- package/src/engine/callResolver.ts +61 -28
- package/src/engine/engine.ts +26 -7
- package/src/engine/languageService.ts +50 -16
- package/src/engine/scanner.ts +285 -42
- package/src/types.ts +6 -1
- package/src/utils/config.ts +0 -1
- package/src/utils/processFile.ts +3 -3
- package/src/utils/universal.ts +149 -77
- package/tests/run.ts +0 -1
- package/dist/engine/trackingDetector.js +0 -17
- package/src/engine/trackingDetector.ts +0 -17
package/src/utils/universal.ts
CHANGED
|
@@ -1,28 +1,77 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import { ParseResult } from "../types";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/* ---------------------------------- */
|
|
5
|
+
/* COMMENT STRIP (SAFE) */
|
|
6
|
+
/* ---------------------------------- */
|
|
5
7
|
function stripComments(input: string): string {
|
|
6
8
|
return input
|
|
7
9
|
.replace(/<!--[\s\S]*?-->/g, "")
|
|
8
|
-
.replace(/\/\*[\s\S]*?\*\//g, "")
|
|
9
|
-
.replace(/\/\/.*$/gm, "");
|
|
10
|
+
.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
/* ---------------------------------- */
|
|
14
|
+
/* TRACK DETECTOR */
|
|
15
|
+
/* ---------------------------------- */
|
|
13
16
|
function looksLikeTracking(code: string) {
|
|
14
|
-
return
|
|
17
|
+
return /\btrack\s*\(|\.track\s*\(/.test(code);
|
|
15
18
|
}
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
/* ---------------------------------- */
|
|
21
|
+
/* SAFE {} PARSER (JSX / TEMPLATES) */
|
|
22
|
+
/* ---------------------------------- */
|
|
23
|
+
function extractBracedExpressions(input: string): string[] {
|
|
24
|
+
const result: string[] = [];
|
|
25
|
+
|
|
26
|
+
let depth = 0;
|
|
27
|
+
let start = -1;
|
|
28
|
+
let inString: string | null = null;
|
|
29
|
+
|
|
30
|
+
for (let i = 0; i < input.length; i++) {
|
|
31
|
+
const char = input[i];
|
|
32
|
+
|
|
33
|
+
// handle strings
|
|
34
|
+
if (inString) {
|
|
35
|
+
if (char === inString && input[i - 1] !== "\\") {
|
|
36
|
+
inString = null;
|
|
37
|
+
}
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
42
|
+
inString = char;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (char === "{") {
|
|
47
|
+
if (depth === 0) start = i + 1;
|
|
48
|
+
depth++;
|
|
49
|
+
} else if (char === "}") {
|
|
50
|
+
depth--;
|
|
51
|
+
if (depth === 0 && start !== -1) {
|
|
52
|
+
const expr = input.slice(start, i);
|
|
53
|
+
|
|
54
|
+
if (looksLikeTracking(expr)) {
|
|
55
|
+
result.push(expr);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
start = -1;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* ---------------------------------- */
|
|
67
|
+
/* HTML HANDLERS */
|
|
68
|
+
/* ---------------------------------- */
|
|
18
69
|
function extractHTMLHandlers(input: string): string[] {
|
|
19
70
|
const result: string[] = [];
|
|
20
71
|
|
|
21
|
-
const
|
|
22
|
-
/\bon\w+\s*=\s*["']([^"']+)["']/g
|
|
23
|
-
);
|
|
72
|
+
const regex = /\bon\w+\s*=\s*["']([^"']+)["']/g;
|
|
24
73
|
|
|
25
|
-
for (const m of
|
|
74
|
+
for (const m of input.matchAll(regex)) {
|
|
26
75
|
if (looksLikeTracking(m[1])) {
|
|
27
76
|
result.push(m[1]);
|
|
28
77
|
}
|
|
@@ -31,15 +80,15 @@ function extractHTMLHandlers(input: string): string[] {
|
|
|
31
80
|
return result;
|
|
32
81
|
}
|
|
33
82
|
|
|
34
|
-
|
|
83
|
+
/* ---------------------------------- */
|
|
84
|
+
/* VUE HANDLERS */
|
|
85
|
+
/* ---------------------------------- */
|
|
35
86
|
function extractVueHandlers(input: string): string[] {
|
|
36
87
|
const result: string[] = [];
|
|
37
88
|
|
|
38
|
-
const
|
|
39
|
-
/(?:@|v-on:)[\w:-]+\s*=\s*["']([^"']+)["']/g
|
|
40
|
-
);
|
|
89
|
+
const regex = /(?:@|v-on:)[\w:-]+\s*=\s*["']([^"']+)["']/g;
|
|
41
90
|
|
|
42
|
-
for (const m of
|
|
91
|
+
for (const m of input.matchAll(regex)) {
|
|
43
92
|
if (looksLikeTracking(m[1])) {
|
|
44
93
|
result.push(m[1]);
|
|
45
94
|
}
|
|
@@ -48,51 +97,95 @@ function extractVueHandlers(input: string): string[] {
|
|
|
48
97
|
return result;
|
|
49
98
|
}
|
|
50
99
|
|
|
51
|
-
|
|
100
|
+
/* ---------------------------------- */
|
|
101
|
+
/* SVELTE HANDLERS */
|
|
102
|
+
/* ---------------------------------- */
|
|
52
103
|
function extractSvelteHandlers(input: string): string[] {
|
|
53
104
|
const result: string[] = [];
|
|
54
105
|
|
|
55
|
-
const
|
|
56
|
-
/\bon:[\w]+\s*=\s*{([^}]+)}/g
|
|
57
|
-
);
|
|
106
|
+
const regex = /\bon:[\w]+\s*=\s*{([\s\S]*?)}/g;
|
|
58
107
|
|
|
59
|
-
for (const m of
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
108
|
+
for (const m of input.matchAll(regex)) {
|
|
109
|
+
const expr = m[1];
|
|
110
|
+
|
|
111
|
+
const nested = extractBracedExpressions(`{${expr}}`);
|
|
112
|
+
result.push(...nested);
|
|
63
113
|
}
|
|
64
114
|
|
|
65
115
|
return result;
|
|
66
116
|
}
|
|
67
117
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
118
|
+
/* ---------------------------------- */
|
|
119
|
+
/* SCRIPT EXTRACTION */
|
|
120
|
+
/* ---------------------------------- */
|
|
121
|
+
function extractScripts(input: string, file: string) {
|
|
122
|
+
const scripts: string[] = [];
|
|
123
|
+
const deps: string[] = [];
|
|
71
124
|
|
|
72
|
-
|
|
125
|
+
// <script src="">
|
|
126
|
+
const srcRegex =
|
|
127
|
+
/<script\b[^>]*?\bsrc=["'](.+?)["'][^>]*>/gi;
|
|
73
128
|
|
|
74
|
-
for (const m of
|
|
75
|
-
|
|
76
|
-
|
|
129
|
+
for (const m of input.matchAll(srcRegex)) {
|
|
130
|
+
const src = m[1];
|
|
131
|
+
|
|
132
|
+
const resolved = src.startsWith("/")
|
|
133
|
+
? path.resolve(process.cwd(), "." + src)
|
|
134
|
+
: path.resolve(path.dirname(file), src);
|
|
135
|
+
|
|
136
|
+
deps.push(resolved);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// inline <script>
|
|
140
|
+
const scriptRegex =
|
|
141
|
+
/<script\b[^>]*>([\s\S]*?)<\/script>/gi;
|
|
142
|
+
|
|
143
|
+
for (const m of input.matchAll(scriptRegex)) {
|
|
144
|
+
if (m[1]?.trim()) {
|
|
145
|
+
scripts.push(m[1]);
|
|
77
146
|
}
|
|
78
147
|
}
|
|
79
148
|
|
|
80
|
-
|
|
149
|
+
const noScripts = input.replace(scriptRegex, "");
|
|
150
|
+
|
|
151
|
+
return { scripts, deps, noScripts };
|
|
81
152
|
}
|
|
82
153
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
154
|
+
/* ---------------------------------- */
|
|
155
|
+
/* STATIC IMPORTS */
|
|
156
|
+
/* ---------------------------------- */
|
|
157
|
+
function extractStaticImports(input: string, file: string) {
|
|
158
|
+
const deps: string[] = [];
|
|
159
|
+
|
|
160
|
+
const regex =
|
|
161
|
+
/import\s+(?:.+?\s+from\s+)?["'](.+?)["']/g;
|
|
162
|
+
|
|
163
|
+
for (const m of input.matchAll(regex)) {
|
|
164
|
+
const mod = m[1];
|
|
165
|
+
|
|
166
|
+
if (!mod.startsWith(".") && !mod.startsWith("/")) continue;
|
|
167
|
+
|
|
168
|
+
const resolved = path.resolve(
|
|
169
|
+
path.dirname(file),
|
|
170
|
+
mod
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
deps.push(resolved);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return deps;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* ---------------------------------- */
|
|
180
|
+
/* DYNAMIC IMPORTS */
|
|
181
|
+
/* ---------------------------------- */
|
|
182
|
+
function extractDynamicImports(input: string, file: string) {
|
|
88
183
|
const deps: string[] = [];
|
|
89
184
|
const calls: string[] = [];
|
|
90
185
|
|
|
91
|
-
const
|
|
92
|
-
/import\(\s*["'](.+?)["']\s*\)/g
|
|
93
|
-
);
|
|
186
|
+
const regex = /import\(\s*["'](.+?)["']\s*\)/g;
|
|
94
187
|
|
|
95
|
-
for (const m of
|
|
188
|
+
for (const m of input.matchAll(regex)) {
|
|
96
189
|
const mod = m[1];
|
|
97
190
|
|
|
98
191
|
const resolved = mod.startsWith("/")
|
|
@@ -109,7 +202,9 @@ function extractDynamicImports(
|
|
|
109
202
|
return { deps, calls };
|
|
110
203
|
}
|
|
111
204
|
|
|
112
|
-
|
|
205
|
+
/* ---------------------------------- */
|
|
206
|
+
/* MAIN */
|
|
207
|
+
/* ---------------------------------- */
|
|
113
208
|
export function parseUniversal(
|
|
114
209
|
content: string,
|
|
115
210
|
file: string
|
|
@@ -119,53 +214,30 @@ export function parseUniversal(
|
|
|
119
214
|
|
|
120
215
|
const clean = stripComments(content);
|
|
121
216
|
|
|
122
|
-
|
|
123
|
-
const fm = clean.match(
|
|
217
|
+
/* ---------- ASTRO FRONTMATTER ---------- */
|
|
218
|
+
const fm = clean.match(/^\s*---([\s\S]*?)---/);
|
|
124
219
|
if (fm?.[1]) {
|
|
125
220
|
parts.push(fm[1]);
|
|
126
221
|
}
|
|
127
222
|
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
for (const s of scriptSrc) {
|
|
134
|
-
const src = s[1];
|
|
223
|
+
/* ---------- SCRIPTS ---------- */
|
|
224
|
+
const { scripts, deps: scriptDeps, noScripts } =
|
|
225
|
+
extractScripts(clean, file);
|
|
135
226
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
: path.resolve(path.dirname(file), src);
|
|
227
|
+
parts.push(...scripts);
|
|
228
|
+
deps.push(...scriptDeps);
|
|
139
229
|
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// INLINE <script>
|
|
144
|
-
const scripts = clean.matchAll(
|
|
145
|
-
/<script\b([^>]*)>([\s\S]*?)<\/script>/g
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
for (const m of scripts) {
|
|
149
|
-
if (m[2].trim()) {
|
|
150
|
-
parts.push(m[2]);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// TEMPLATE PART
|
|
155
|
-
const noScripts = clean.replace(
|
|
156
|
-
/<script[\s\S]*?<\/script>/g,
|
|
157
|
-
""
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
// handlers
|
|
230
|
+
/* ---------- HANDLERS ---------- */
|
|
161
231
|
parts.push(...extractHTMLHandlers(noScripts));
|
|
162
232
|
parts.push(...extractVueHandlers(noScripts));
|
|
163
233
|
parts.push(...extractSvelteHandlers(noScripts));
|
|
164
234
|
|
|
165
|
-
|
|
166
|
-
parts.push(...
|
|
235
|
+
/* ---------- JSX / TEMPLATE ---------- */
|
|
236
|
+
parts.push(...extractBracedExpressions(clean));
|
|
237
|
+
|
|
238
|
+
/* ---------- IMPORTS ---------- */
|
|
239
|
+
deps.push(...extractStaticImports(clean, file));
|
|
167
240
|
|
|
168
|
-
// dynamic imports
|
|
169
241
|
const dyn = extractDynamicImports(clean, file);
|
|
170
242
|
deps.push(...dyn.deps);
|
|
171
243
|
parts.push(...dyn.calls);
|
package/tests/run.ts
CHANGED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.isTrackingCall = isTrackingCall;
|
|
7
|
-
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
-
function isTrackingCall(node) {
|
|
9
|
-
const expr = node.expression;
|
|
10
|
-
if (typescript_1.default.isIdentifier(expr)) {
|
|
11
|
-
return expr.text === "track";
|
|
12
|
-
}
|
|
13
|
-
if (typescript_1.default.isPropertyAccessExpression(expr)) {
|
|
14
|
-
return expr.name.text === "track";
|
|
15
|
-
}
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import ts from "typescript";
|
|
2
|
-
|
|
3
|
-
export function isTrackingCall(
|
|
4
|
-
node: ts.CallExpression
|
|
5
|
-
): boolean {
|
|
6
|
-
const expr = node.expression;
|
|
7
|
-
|
|
8
|
-
if (ts.isIdentifier(expr)) {
|
|
9
|
-
return expr.text === "track";
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
if (ts.isPropertyAccessExpression(expr)) {
|
|
13
|
-
return expr.name.text === "track";
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return false;
|
|
17
|
-
}
|