@rspnseapp/dev-inspector 0.1.0
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/LICENSE +21 -0
- package/README.md +65 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.inspector.js +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Rspnse
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# @rspnseapp/dev-inspector
|
|
2
|
+
|
|
3
|
+
A Vite plugin that enables Rspnse inspect functionality on localhost dev servers without requiring a browser extension.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @rspnseapp/dev-inspector --save-dev
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Add the plugin to your Vite config:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
// vite.config.ts
|
|
17
|
+
import { defineConfig } from 'vite';
|
|
18
|
+
import { rspnseInspector } from '@rspnseapp/dev-inspector';
|
|
19
|
+
|
|
20
|
+
export default defineConfig({
|
|
21
|
+
plugins: [rspnseInspector()]
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Then:
|
|
26
|
+
1. Start your dev server (e.g., `npm run dev`)
|
|
27
|
+
2. Open [rspnse.net](https://rspnse.net)
|
|
28
|
+
3. Enter your localhost URL (e.g., `http://localhost:5173`)
|
|
29
|
+
4. Use the inspect feature - works in any browser!
|
|
30
|
+
|
|
31
|
+
## Options
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
rspnseInspector({
|
|
35
|
+
// Disable the inspector (defaults to true)
|
|
36
|
+
enabled: true,
|
|
37
|
+
|
|
38
|
+
// Add additional trusted origins beyond the defaults
|
|
39
|
+
trustedOrigins: ['https://custom-domain.com']
|
|
40
|
+
})
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## How It Works
|
|
44
|
+
|
|
45
|
+
The plugin injects a small script into your dev server pages that:
|
|
46
|
+
- Listens for postMessage commands from rspnse.net
|
|
47
|
+
- Enables element inspection with hover highlighting
|
|
48
|
+
- Captures computed styles from selected elements
|
|
49
|
+
- Allows CSS injection for live editing
|
|
50
|
+
|
|
51
|
+
Communication uses the same protocol as the browser extension, so the main Rspnse app works seamlessly with either approach.
|
|
52
|
+
|
|
53
|
+
## Security
|
|
54
|
+
|
|
55
|
+
- Only responds to messages from trusted origins (rspnse.net and localhost by default)
|
|
56
|
+
- Only runs in development mode (not included in production builds)
|
|
57
|
+
- No data is sent to any external servers
|
|
58
|
+
|
|
59
|
+
## Browser Support
|
|
60
|
+
|
|
61
|
+
Works in all modern browsers - Chrome, Firefox, Safari, and Edge.
|
|
62
|
+
|
|
63
|
+
## License
|
|
64
|
+
|
|
65
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
|
|
3
|
+
interface BreadcrumbItem {
|
|
4
|
+
label: string;
|
|
5
|
+
index: number;
|
|
6
|
+
}
|
|
7
|
+
interface InspectedElement {
|
|
8
|
+
selector: string;
|
|
9
|
+
tagName: string;
|
|
10
|
+
classList: string[];
|
|
11
|
+
id: string | null;
|
|
12
|
+
computedStyles: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
interface StyleEntry {
|
|
15
|
+
type: 'inline' | 'external';
|
|
16
|
+
index?: number;
|
|
17
|
+
href?: string;
|
|
18
|
+
css: string | null;
|
|
19
|
+
error?: string;
|
|
20
|
+
}
|
|
21
|
+
interface RspnseInspectorOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Enable/disable the inspector. Defaults to true in development.
|
|
24
|
+
*/
|
|
25
|
+
enabled?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Trusted origins that can communicate with the inspector.
|
|
28
|
+
* Defaults to ['https://rspnse.net', 'http://localhost']
|
|
29
|
+
*/
|
|
30
|
+
trustedOrigins?: string[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Vite plugin that injects the Rspnse inspector script into dev server pages.
|
|
35
|
+
* This enables inspect functionality from rspnse.net without a browser extension.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* // vite.config.ts
|
|
40
|
+
* import { rspnseInspector } from '@rspnseapp/dev-inspector';
|
|
41
|
+
*
|
|
42
|
+
* export default {
|
|
43
|
+
* plugins: [rspnseInspector()]
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
declare function rspnseInspector(options?: RspnseInspectorOptions): Plugin;
|
|
48
|
+
|
|
49
|
+
export { type BreadcrumbItem, type InspectedElement, type RspnseInspectorOptions, type StyleEntry, rspnseInspector };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var RspnseInspector=(()=>{var f="rspnse-injected-css",p="rspnse-inspect-highlight",w="rspnse-inspect-label",x="rspnse-inspect-margin",S="rspnse-inspect-padding",g="1.0.0",C=["https://rspnse.net","https://www.rspnse.net","http://localhost","http://127.0.0.1"];function G(){return window.__RSPNSE_TRUSTED_ORIGINS__&&Array.isArray(window.__RSPNSE_TRUSTED_ORIGINS__)?[...C,...window.__RSPNSE_TRUSTED_ORIGINS__]:C}var m=!1,u=null,c=null,M={layout:["display","position","top","right","bottom","left","z-index"],flexbox:["flex","flex-direction","flex-wrap","justify-content","align-items","align-content","gap","row-gap","column-gap"],grid:["grid-template-columns","grid-template-rows","grid-column","grid-row"],box:["width","height","min-width","max-width","min-height","max-height","margin","margin-top","margin-right","margin-bottom","margin-left","padding","padding-top","padding-right","padding-bottom","padding-left","border","border-radius","box-sizing"],typography:["font-family","font-size","font-weight","font-style","line-height","letter-spacing","text-align","text-decoration","text-transform","color","white-space"],background:["background","background-color","background-image","background-size","background-position"],visual:["opacity","visibility","overflow","overflow-x","overflow-y","box-shadow","transform","cursor"]};function F(t){return G().some(n=>n.startsWith("http://localhost")||n.startsWith("http://127.0.0.1")?t.startsWith("http://localhost")||t.startsWith("http://127.0.0.1"):t===n||t.startsWith(n))}function H(t){let e=document.getElementById(f);return e||(e=document.createElement("style"),e.id=f,(document.head||document.documentElement).appendChild(e)),e.textContent=t,{success:!0}}function U(){let t=document.getElementById(f);return t?(t.remove(),{success:!0}):{success:!1,error:"No styles to remove"}}function V(){let t=document.getElementById(f);return t&&t.textContent||""}async function j(){let t=[];document.querySelectorAll("style").forEach((s,i)=>{s.textContent&&s.id!==f&&t.push({type:"inline",index:i+1,css:s.textContent.trim()})});let n=document.querySelectorAll('link[rel="stylesheet"]');for(let s of Array.from(n)){let i=s.href;try{let o=await fetch(i);if(o.ok){let r=await o.text();t.push({type:"external",href:i,css:r.trim()})}}catch(o){t.push({type:"external",href:i,css:null,error:`Could not fetch: ${o.message}`})}}return t}function z(t){if(t.id)return"#"+CSS.escape(t.id);let e=[],n=t,s=0;for(;n&&n!==document.body&&n!==document.documentElement&&s<3;){let i=n.tagName.toLowerCase();if(n.className&&typeof n.className=="string"){let o=n.className.trim().split(/\s+/).filter(r=>r&&!r.startsWith("rspnse-")).slice(0,2);o.length>0&&(i+="."+o.map(r=>CSS.escape(r)).join("."))}if(n.parentElement){let o=Array.from(n.parentElement.children).filter(r=>r.tagName===n.tagName);if(o.length>1){let r=o.indexOf(n)+1;i+=`:nth-of-type(${r})`}}e.unshift(i),n=n.parentElement,s++}return e.join(" > ")}function L(t){let e=window.getComputedStyle(t),n={},s=document.createElement(t.tagName);s.style.cssText="position: absolute; visibility: hidden;",document.body.appendChild(s);let i=window.getComputedStyle(s);return Object.keys(M).forEach(o=>{M[o].forEach(r=>{let l=e.getPropertyValue(r),E=i.getPropertyValue(r);l&&l!==E&&l!=="none"&&l!=="auto"&&l!=="normal"&&l!=="0px"&&l!=="rgba(0, 0, 0, 0)"&&(n[r]=l)})}),s.remove(),{selector:z(t),tagName:t.tagName.toLowerCase(),classList:Array.from(t.classList),id:t.id||null,computedStyles:n}}function P(t){let e=[],n=t;for(;n&&n!==document.documentElement;){if(n.nodeType!==1){n=n.parentElement;continue}let s=n.tagName.toLowerCase(),i=n.id?"#"+n.id:"",o=n.className&&typeof n.className=="string"?"."+n.className.trim().split(/\s+/).filter(r=>r&&!r.startsWith("rspnse-")).slice(0,1).join("."):"";e.unshift({label:s+i+o,index:e.length}),n=n.parentElement}e.unshift({label:"html",index:e.length});for(let s=0;s<e.length;s++)e[s].index=s;return e}function Y(t){if(!c)return null;let e=[],n=c;for(;n&&n!==document.documentElement;)n.nodeType===1&&e.unshift(n),n=n.parentElement;return e.unshift(document.documentElement),e[t]||null}function q(t){let e=t.tagName.toLowerCase(),n=t.id?"#"+t.id:"",s=t.className&&typeof t.className=="string"?"."+t.className.trim().split(/\s+/).filter(i=>i&&!i.startsWith("rspnse-")).slice(0,2).join("."):"";return e+n+s}function X(){[p,w,x,S].forEach(i=>{let o=document.getElementById(i);o&&o.remove()});let t=document.createElement("div");t.id=p,t.style.cssText="position: fixed; pointer-events: none; z-index: 2147483646; border: 2px solid #3b82f6; background: rgba(59, 130, 246, 0.15); transition: all 0.05s ease-out; display: none;",document.body.appendChild(t);let e=document.createElement("div");e.id=x,e.style.cssText="position: fixed; pointer-events: none; z-index: 2147483645; background: rgba(249, 115, 22, 0.25); transition: all 0.05s ease-out; display: none;",document.body.appendChild(e);let n=document.createElement("div");n.id=S,n.style.cssText="position: fixed; pointer-events: none; z-index: 2147483644; background: rgba(34, 197, 94, 0.25); transition: all 0.05s ease-out; display: none;",document.body.appendChild(n);let s=document.createElement("div");return s.id=w,s.style.cssText="position: fixed; pointer-events: none; z-index: 2147483647; background: #1e293b; color: #f8fafc; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 11px; padding: 4px 8px; border-radius: 4px; white-space: nowrap; display: none; box-shadow: 0 2px 8px rgba(0,0,0,0.3); max-width: calc(100vw - 16px); overflow: hidden; text-overflow: ellipsis;",document.body.appendChild(s),t}function k(t){let e=document.getElementById(p),n=document.getElementById(w),s=document.getElementById(x),i=document.getElementById(S);if(!e||!n)return;if(!t){e.style.display="none",n.style.display="none",s&&(s.style.display="none"),i&&(i.style.display="none");return}let o=t.getBoundingClientRect(),r=window.getComputedStyle(t),l=parseFloat(r.marginTop)||0,E=parseFloat(r.marginRight)||0,R=parseFloat(r.marginBottom)||0,d=parseFloat(r.marginLeft)||0,h=parseFloat(r.paddingTop)||0,b=parseFloat(r.paddingRight)||0,I=parseFloat(r.paddingBottom)||0,y=parseFloat(r.paddingLeft)||0;e.style.display="block",e.style.top=o.top+"px",e.style.left=o.left+"px",e.style.width=o.width+"px",e.style.height=o.height+"px",s&&(l||E||R||d)?(s.style.display="block",s.style.top=o.top-l+"px",s.style.left=o.left-d+"px",s.style.width=o.width+d+E+"px",s.style.height=o.height+l+R+"px",s.style.clipPath=`polygon(0 0, 100% 0, 100% 100%, 0 100%, 0 0, ${d}px ${l}px, ${d}px ${l+o.height}px, ${d+o.width}px ${l+o.height}px, ${d+o.width}px ${l}px, ${d}px ${l}px)`):s&&(s.style.display="none"),i&&(h||b||I||y)?(i.style.display="block",i.style.top=o.top+"px",i.style.left=o.left+"px",i.style.width=o.width+"px",i.style.height=o.height+"px",i.style.clipPath=`polygon(0 0, 100% 0, 100% 100%, 0 100%, 0 0, ${y}px ${h}px, ${y}px ${o.height-I}px, ${o.width-b}px ${o.height-I}px, ${o.width-b}px ${h}px, ${y}px ${h}px)`):i&&(i.style.display="none");let B=q(t),W=`${Math.round(o.width)} x ${Math.round(o.height)}`;n.innerHTML=`<span style="color: #93c5fd;">${B}</span> <span style="color: #94a3b8; margin-left: 6px;">${W}</span>`,n.style.display="block",n.style.left="auto",n.style.right="auto";let v=window.innerWidth,_=o.top-24-6;_<4&&(_=o.bottom+6),n.style.top=_+"px",o.left+o.width/2>v/2?(n.style.right=Math.max(4,v-o.right)+"px",n.style.left="auto"):(n.style.left=Math.max(4,o.left)+"px",n.style.right="auto")}function N(t){if(!c)return-1;let e=[],n=c;for(;n&&n!==document.documentElement;)n.nodeType===1&&e.unshift(n),n=n.parentElement;e.unshift(document.documentElement);for(let s=0;s<e.length;s++)if(e[s]===t)return s;return-1}function T(t){if(!t||t.id&&t.id.startsWith("rspnse-"))return!1;u=t,k(t);let e=L(t),n=P(c),s=N(t);return window.parent!==window&&window.parent.postMessage({type:"RSPNSE_INSPECT_ELEMENT_RESULT",success:!0,element:e,breadcrumb:n,breadcrumbIndex:s},"*"),!0}function O(t){if(!m)return;let e=document.elementFromPoint(t.clientX,t.clientY);e&&e.id!==p&&k(e)}function A(t){if(!m)return;t.preventDefault(),t.stopPropagation();let e=document.elementFromPoint(t.clientX,t.clientY);if(e&&e.id!==p&&!e.id?.startsWith("rspnse-")){c=e,u=e;let n=L(e),s=P(e);window.parent!==window&&window.parent.postMessage({type:"RSPNSE_INSPECT_ELEMENT_RESULT",success:!0,element:n,breadcrumb:s,breadcrumbIndex:s.length-1},"*")}}function $(t){if(!m)return;if(t.key==="Escape"){D(),window.parent!==window&&window.parent.postMessage({type:"RSPNSE_INSPECT_CANCELLED",reason:"escape"},"*");return}if(!u||!c)return;let e=N(u),n=[],s=c;for(;s&&s!==document.documentElement;)s.nodeType===1&&n.unshift(s),s=s.parentElement;n.unshift(document.documentElement);let i=e;switch(t.key){case"ArrowUp":case"ArrowLeft":i=e-1;break;case"ArrowDown":case"ArrowRight":i=e+1;break;default:return}i>=0&&i<n.length&&(t.preventDefault(),T(n[i]))}function K(){m||(m=!0,document.body.style.cursor="crosshair",X(),document.addEventListener("mousemove",O,!0),document.addEventListener("click",A,!0),document.addEventListener("keydown",$,!0))}function D(){m=!1,u=null,c=null,document.body.style.cursor="",[p,w,x,S].forEach(t=>{let e=document.getElementById(t);e&&e.remove()}),document.removeEventListener("mousemove",O,!0),document.removeEventListener("click",A,!0),document.removeEventListener("keydown",$,!0)}function a(t,e,n){if(t.source&&t.source!==window)try{t.source.postMessage({type:e.type+"_RESULT",requestId:e.requestId,frameId:e.frameId,...n},"*")}catch{}}function J(t){if(!F(t.origin))return;let e=t.data;if(!(!e||typeof e!="object")&&e.type&&e.type.startsWith("RSPNSE_"))switch(e.type){case"RSPNSE_INJECT_CSS":typeof e.css=="string"?a(t,e,H(e.css)):a(t,e,{success:!1,error:"CSS must be a string"});break;case"RSPNSE_REMOVE_CSS":a(t,e,U());break;case"RSPNSE_GET_CSS":a(t,e,{success:!0,css:V()});break;case"RSPNSE_CAPTURE_STYLES":j().then(n=>{a(t,e,{success:!0,styles:n})}).catch(n=>{a(t,e,{success:!1,error:n.message})});break;case"RSPNSE_INSPECT_START":K(),a(t,e,{success:!0});break;case"RSPNSE_INSPECT_STOP":D(),a(t,e,{success:!0});break;case"RSPNSE_INSPECT_NAVIGATE_TO":if(c&&typeof e.breadcrumbIndex=="number"){let n=Y(e.breadcrumbIndex);n?(T(n),a(t,e,{success:!0})):a(t,e,{success:!1,error:"Element not found"})}else a(t,e,{success:!1,error:"No original element or invalid index"});break;case"RSPNSE_INSPECT_NAVIGATE":if(c&&u&&e.direction){let n=N(u),s=[],i=c;for(;i&&i!==document.documentElement;)i.nodeType===1&&s.unshift(i),i=i.parentElement;s.unshift(document.documentElement);let o=n;(e.direction==="left"||e.direction==="up")&&(o=n-1),(e.direction==="right"||e.direction==="down")&&(o=n+1),o>=0&&o<s.length?(T(s[o]),a(t,e,{success:!0})):a(t,e,{success:!1,error:"At end of breadcrumb"})}else a(t,e,{success:!1,error:"No selection"});break;case"RSPNSE_PING":a(t,e,{success:!0,pong:!0,version:g});break}}function Q(){if(document.documentElement.setAttribute("data-rspnse-inspector",g),window.addEventListener("message",J),window.parent!==window)try{window.parent.postMessage({type:"RSPNSE_DEV_INSPECTOR_READY",version:g,url:window.location.href},"*"),window.parent.postMessage({type:"RSPNSE_EXTENSION_READY",version:g,url:window.location.href},"*")}catch{}window.dispatchEvent(new CustomEvent("rspnse-inspector-loaded",{detail:{version:g}}))}Q();})();
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// src/vite-plugin.ts
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { resolve, dirname } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
function rspnseInspector(options = {}) {
|
|
7
|
+
const { enabled = true, trustedOrigins } = options;
|
|
8
|
+
let inspectorScript = null;
|
|
9
|
+
function getInspectorScript() {
|
|
10
|
+
if (inspectorScript) return inspectorScript;
|
|
11
|
+
try {
|
|
12
|
+
const scriptPath = resolve(__dirname, "../dist/index.inspector.js");
|
|
13
|
+
inspectorScript = readFileSync(scriptPath, "utf-8");
|
|
14
|
+
} catch {
|
|
15
|
+
try {
|
|
16
|
+
const scriptPath = resolve(__dirname, "./index.inspector.js");
|
|
17
|
+
inspectorScript = readFileSync(scriptPath, "utf-8");
|
|
18
|
+
} catch {
|
|
19
|
+
console.warn(
|
|
20
|
+
"[@rspnseapp/dev-inspector] Could not load inspector script. Run `npm run build` first."
|
|
21
|
+
);
|
|
22
|
+
inspectorScript = "// Inspector script not found";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return inspectorScript;
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
name: "rspnse-inspector",
|
|
29
|
+
// Only apply in dev mode
|
|
30
|
+
apply: "serve",
|
|
31
|
+
configureServer(server) {
|
|
32
|
+
if (!enabled) return;
|
|
33
|
+
server.middlewares.use((req, res, next) => {
|
|
34
|
+
if (req.url === "/@rspnse-inspector/inspector.js") {
|
|
35
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
36
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
37
|
+
let script = getInspectorScript();
|
|
38
|
+
if (trustedOrigins && trustedOrigins.length > 0) {
|
|
39
|
+
const originsArray = JSON.stringify(trustedOrigins);
|
|
40
|
+
script = `window.__RSPNSE_TRUSTED_ORIGINS__ = ${originsArray};
|
|
41
|
+
${script}`;
|
|
42
|
+
}
|
|
43
|
+
res.end(script);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
next();
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
transformIndexHtml(html) {
|
|
50
|
+
if (!enabled) return html;
|
|
51
|
+
const scriptTag = `<script src="/@rspnse-inspector/inspector.js" defer></script>`;
|
|
52
|
+
if (html.includes("</head>")) {
|
|
53
|
+
return html.replace("</head>", `${scriptTag}
|
|
54
|
+
</head>`);
|
|
55
|
+
}
|
|
56
|
+
if (html.includes("<body")) {
|
|
57
|
+
return html.replace(/<body([^>]*)>/, `<body$1>
|
|
58
|
+
${scriptTag}`);
|
|
59
|
+
}
|
|
60
|
+
return scriptTag + "\n" + html;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
rspnseInspector
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vite-plugin.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport { readFileSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { RspnseInspectorOptions } from './types';\n\n// Get the directory of this module\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Vite plugin that injects the Rspnse inspector script into dev server pages.\n * This enables inspect functionality from rspnse.net without a browser extension.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { rspnseInspector } from '@rspnseapp/dev-inspector';\n *\n * export default {\n * plugins: [rspnseInspector()]\n * }\n * ```\n */\nexport function rspnseInspector(options: RspnseInspectorOptions = {}): Plugin {\n const { enabled = true, trustedOrigins } = options;\n\n // Cache the inspector script content\n let inspectorScript: string | null = null;\n\n function getInspectorScript(): string {\n if (inspectorScript) return inspectorScript;\n\n try {\n // Try to load the bundled inspector script\n const scriptPath = resolve(__dirname, '../dist/index.inspector.js');\n inspectorScript = readFileSync(scriptPath, 'utf-8');\n } catch {\n // Fallback: load from same directory (during development)\n try {\n const scriptPath = resolve(__dirname, './index.inspector.js');\n inspectorScript = readFileSync(scriptPath, 'utf-8');\n } catch {\n console.warn(\n '[@rspnseapp/dev-inspector] Could not load inspector script. Run `npm run build` first.'\n );\n inspectorScript = '// Inspector script not found';\n }\n }\n\n return inspectorScript;\n }\n\n return {\n name: 'rspnse-inspector',\n\n // Only apply in dev mode\n apply: 'serve',\n\n configureServer(server) {\n if (!enabled) return;\n\n // Serve the inspector script at a special path\n server.middlewares.use((req, res, next) => {\n if (req.url === '/@rspnse-inspector/inspector.js') {\n res.setHeader('Content-Type', 'application/javascript');\n res.setHeader('Cache-Control', 'no-cache');\n\n let script = getInspectorScript();\n\n // If custom trusted origins are provided, inject them\n if (trustedOrigins && trustedOrigins.length > 0) {\n const originsArray = JSON.stringify(trustedOrigins);\n script = `window.__RSPNSE_TRUSTED_ORIGINS__ = ${originsArray};\\n${script}`;\n }\n\n res.end(script);\n return;\n }\n next();\n });\n },\n\n transformIndexHtml(html) {\n if (!enabled) return html;\n\n // Inject the inspector script before </head>\n const scriptTag = `<script src=\"/@rspnse-inspector/inspector.js\" defer></script>`;\n\n if (html.includes('</head>')) {\n return html.replace('</head>', `${scriptTag}\\n</head>`);\n }\n\n // Fallback: inject at start of body if no head tag\n if (html.includes('<body')) {\n return html.replace(/<body([^>]*)>/, `<body$1>\\n${scriptTag}`);\n }\n\n // Last resort: prepend to html\n return scriptTag + '\\n' + html;\n },\n };\n}\n"],"mappings":";AACA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB;AAI9B,IAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAgBjD,SAAS,gBAAgB,UAAkC,CAAC,GAAW;AAC5E,QAAM,EAAE,UAAU,MAAM,eAAe,IAAI;AAG3C,MAAI,kBAAiC;AAErC,WAAS,qBAA6B;AACpC,QAAI,gBAAiB,QAAO;AAE5B,QAAI;AAEF,YAAM,aAAa,QAAQ,WAAW,4BAA4B;AAClE,wBAAkB,aAAa,YAAY,OAAO;AAAA,IACpD,QAAQ;AAEN,UAAI;AACF,cAAM,aAAa,QAAQ,WAAW,sBAAsB;AAC5D,0BAAkB,aAAa,YAAY,OAAO;AAAA,MACpD,QAAQ;AACN,gBAAQ;AAAA,UACN;AAAA,QACF;AACA,0BAAkB;AAAA,MACpB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA;AAAA,IAGN,OAAO;AAAA,IAEP,gBAAgB,QAAQ;AACtB,UAAI,CAAC,QAAS;AAGd,aAAO,YAAY,IAAI,CAAC,KAAK,KAAK,SAAS;AACzC,YAAI,IAAI,QAAQ,mCAAmC;AACjD,cAAI,UAAU,gBAAgB,wBAAwB;AACtD,cAAI,UAAU,iBAAiB,UAAU;AAEzC,cAAI,SAAS,mBAAmB;AAGhC,cAAI,kBAAkB,eAAe,SAAS,GAAG;AAC/C,kBAAM,eAAe,KAAK,UAAU,cAAc;AAClD,qBAAS,uCAAuC,YAAY;AAAA,EAAM,MAAM;AAAA,UAC1E;AAEA,cAAI,IAAI,MAAM;AACd;AAAA,QACF;AACA,aAAK;AAAA,MACP,CAAC;AAAA,IACH;AAAA,IAEA,mBAAmB,MAAM;AACvB,UAAI,CAAC,QAAS,QAAO;AAGrB,YAAM,YAAY;AAElB,UAAI,KAAK,SAAS,SAAS,GAAG;AAC5B,eAAO,KAAK,QAAQ,WAAW,GAAG,SAAS;AAAA,QAAW;AAAA,MACxD;AAGA,UAAI,KAAK,SAAS,OAAO,GAAG;AAC1B,eAAO,KAAK,QAAQ,iBAAiB;AAAA,EAAa,SAAS,EAAE;AAAA,MAC/D;AAGA,aAAO,YAAY,OAAO;AAAA,IAC5B;AAAA,EACF;AACF;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rspnseapp/dev-inspector",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Dev server plugin for Rspnse inspect functionality",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup",
|
|
21
|
+
"dev": "tsup --watch",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"prepublishOnly": "npm run build"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"vite-plugin",
|
|
27
|
+
"rspnse",
|
|
28
|
+
"responsive",
|
|
29
|
+
"inspect",
|
|
30
|
+
"css",
|
|
31
|
+
"devtools"
|
|
32
|
+
],
|
|
33
|
+
"author": "",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/AlexBoghh/Rspnse.git",
|
|
38
|
+
"directory": "packages/dev-inspector"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"vite": ">=4.0.0"
|
|
42
|
+
},
|
|
43
|
+
"peerDependenciesMeta": {
|
|
44
|
+
"vite": {
|
|
45
|
+
"optional": true
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"tsup": "^8.0.0",
|
|
50
|
+
"typescript": "^5.0.0",
|
|
51
|
+
"vite": "^6.0.0"
|
|
52
|
+
}
|
|
53
|
+
}
|