-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinjection-engine.js
More file actions
153 lines (133 loc) · 5.27 KB
/
Copy pathinjection-engine.js
File metadata and controls
153 lines (133 loc) · 5.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Advanced injection engine for HTML, CSS, and JavaScript
class InjectionEngine {
constructor() {
this.injections = {
html: [], // HTML snippets to inject
css: [], // CSS styles to inject
js: [], // JavaScript to inject
head: [], // Raw head content
bodyStart: [], // Content at start of body
bodyEnd: [] // Content at end of body
};
this.assets = new Map(); // Virtual file system for plugin assets
}
// Register HTML injection
injectHTML(position, html, id = null) {
const injection = { html, id, timestamp: Date.now() };
if (['head', 'bodyStart', 'bodyEnd'].includes(position)) {
this.injections[position].push(injection);
} else {
this.injections.html.push({ ...injection, position });
}
return this;
}
// Register CSS injection
injectCSS(css, id = null, important = false) {
this.injections.css.push({ css, id, important, timestamp: Date.now() });
return this;
}
// Register JavaScript injection
injectJS(js, id = null, position = 'bodyEnd') {
this.injections.js.push({ js, id, position, timestamp: Date.now() });
return this;
}
// Register external script URL
injectScript(url, id = null, async = true, position = 'head') {
const script = `<script src="${url}"${async ? ' async' : ''}></script>`;
this.injections[position].push({ html: script, id, timestamp: Date.now() });
return this;
}
// Register external stylesheet
injectStylesheet(url, id = null) {
const link = `<link rel="stylesheet" href="${url}">`;
this.injections.head.push({ html: link, id, timestamp: Date.now() });
return this;
}
// Add virtual asset (served at /_plugins/assets/:id)
addAsset(id, content, contentType = 'text/plain') {
this.assets.set(id, { content, contentType });
return this;
}
// Get asset for serving
getAsset(id) {
return this.assets.get(id);
}
// List all assets
listAssets() {
return Array.from(this.assets.keys());
}
// Remove injection by ID
removeById(id) {
for (const key of Object.keys(this.injections)) {
this.injections[key] = this.injections[key].filter(i => i.id !== id);
}
this.assets.delete(id);
return this;
}
// Process HTML response and apply all injections
processHTML(body) {
// Inject CSS into head
if (this.injections.css.length > 0) {
const cssContent = this.injections.css
.map(c => c.css)
.join('\n');
const styleTag = `<style data-injected="true">\n${cssContent}\n</style>`;
body = this.injectAtPosition(body, 'head', styleTag, 'end');
}
// Inject head content
for (const injection of this.injections.head) {
body = this.injectAtPosition(body, 'head', injection.html, 'end');
}
// Inject bodyStart content
for (const injection of this.injections.bodyStart) {
body = this.injectAtPosition(body, 'body', injection.html, 'start');
}
// Inject JS modules
if (this.injections.js.length > 0) {
const jsContent = this.injections.js
.map(j => j.js)
.join('\n;\n');
const scriptTag = `<script data-injected="true">\n(function(){\n${jsContent}\n})();\n</script>`;
body = this.injectAtPosition(body, 'body', scriptTag, 'end');
}
// Inject bodyEnd content
for (const injection of this.injections.bodyEnd) {
body = this.injectAtPosition(body, 'body', injection.html, 'end');
}
// Generic HTML injections at specific positions
for (const injection of this.injections.html) {
const { position, html } = injection;
if (position.includes('before:')) {
const selector = position.replace('before:', '');
body = body.replace(new RegExp(`(<${selector}[^>]*>)`, 'i'), `${html}$1`);
} else if (position.includes('after:')) {
const selector = position.replace('after:', '');
body = body.replace(new RegExp(`(</${selector}>)`, 'i'), `$1${html}`);
}
}
return body;
}
injectAtPosition(body, tag, content, position) {
const tagRegex = new RegExp(`(<${tag}[^>]*>)`, 'i');
const closeTagRegex = new RegExp(`(</${tag}>)`, 'i');
if (position === 'start' && tagRegex.test(body)) {
return body.replace(tagRegex, `$1${content}`);
} else if (position === 'end' && closeTagRegex.test(body)) {
return body.replace(closeTagRegex, `${content}$1`);
}
return body;
}
// Get current injection stats
getStats() {
return {
html: this.injections.html.length,
css: this.injections.css.length,
js: this.injections.js.length,
head: this.injections.head.length,
bodyStart: this.injections.bodyStart.length,
bodyEnd: this.injections.bodyEnd.length,
assets: this.assets.size
};
}
}
module.exports = InjectionEngine;