more stripping

This commit is contained in:
KingKDot
2026-05-11 00:17:12 -05:00
parent 2a1554b111
commit 76cb47f8eb
2 changed files with 11 additions and 4 deletions
@@ -1114,6 +1114,13 @@ export async function handlePluginRoutes(
const bodyMatch = raw.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
pluginBody = bodyMatch ? bodyMatch[1] : raw;
pluginBody = pluginBody.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, (tag) => {
const srcMatch = tag.match(/\bsrc\s*=\s*["']([^"']+)["']/i);
if (!srcMatch) return tag;
const src = srcMatch[1].split("?")[0].split("#")[0];
return src === `${pluginId}.js` || src.endsWith(`/${pluginId}.js`) ? "" : tag;
});
const headMatch = raw.match(/<head[^>]*>([\s\S]*?)<\/head>/i);
if (headMatch) {
const headContent = headMatch[1];
+4 -4
View File
@@ -630,15 +630,15 @@ element.addEventListener("click", (e) => {
});
```
### Avoiding redeclaration errors
### Script injection
Because the plugin UI is injected into a persistent single-page application, navigating away and back to a plugin page causes the plugin's JS file to be re-evaluated in the **same global scope**. Using top-level `const` / `let` declarations will throw `SyntaxError: Identifier '...' has already been declared` on the second load.
The server auto-injects `<script src="/plugins/<pluginId>/assets/<pluginId>.js"></script>` at the end of the page — you don't need to include it yourself. If your plugin HTML does include `<script src=".../<pluginId>.js">` in its `<body>` (e.g. so the file works standalone in a browser), the server strips that tag during injection to prevent the script from running twice. Other `<script>` tags in the body are left alone.
**Wrap all plugin JS in an IIFE** to scope everything locally:
If you want defensive scoping anyway, wrap your plugin JS in an IIFE so top-level identifiers don't collide with the global scope:
```js
(() => {
const MY_CONST = "value"; // safe — scoped to this closure
const MY_CONST = "value";
// ... rest of plugin code
})();
```