vite-plugin-ai-annotator 1.14.3 → 1.14.4
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 +44 -4
- package/dist/annotator-toolbar.d.ts +1 -0
- package/dist/annotator-toolbar.js +128 -39
- package/dist/nuxt-module.d.ts +5 -0
- package/dist/nuxt-module.js +1528 -0
- package/dist/nuxt-module.js.map +7 -0
- package/package.json +18 -4
package/README.md
CHANGED
|
@@ -28,6 +28,7 @@ Works with all Vite-supported frameworks:
|
|
|
28
28
|
- 🅰️ **Angular** - Recognizes components and directives
|
|
29
29
|
- 🟠 **Svelte** - Identifies components and stores
|
|
30
30
|
- 📄 **Vanilla JS** - Works with plain HTML/CSS/JS
|
|
31
|
+
- 🟦 **Nuxt.js** - Full support via Nuxt module (Nuxt 3+)
|
|
31
32
|
|
|
32
33
|
## Installation
|
|
33
34
|
|
|
@@ -44,13 +45,15 @@ Then ask Claude: *"Set up ai-annotator for my project"* - it handles the rest!
|
|
|
44
45
|
|
|
45
46
|
### Option 2: Manual Setup
|
|
46
47
|
|
|
47
|
-
####
|
|
48
|
+
#### For Vite Projects
|
|
49
|
+
|
|
50
|
+
##### Step 1: Install the package
|
|
48
51
|
|
|
49
52
|
```bash
|
|
50
53
|
bun add -d vite-plugin-ai-annotator
|
|
51
54
|
```
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
##### Step 2: Add to your Vite config
|
|
54
57
|
|
|
55
58
|
```typescript
|
|
56
59
|
import { defineConfig } from 'vite';
|
|
@@ -63,7 +66,33 @@ export default defineConfig({
|
|
|
63
66
|
});
|
|
64
67
|
```
|
|
65
68
|
|
|
66
|
-
####
|
|
69
|
+
#### For Nuxt.js Projects (Nuxt 3+)
|
|
70
|
+
|
|
71
|
+
##### Step 1: Install the package
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
bun add -d vite-plugin-ai-annotator
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
##### Step 2: Add to your `nuxt.config.ts`
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
export default defineNuxtConfig({
|
|
81
|
+
modules: [
|
|
82
|
+
'vite-plugin-ai-annotator/nuxt'
|
|
83
|
+
],
|
|
84
|
+
// Optional: Configure the annotator
|
|
85
|
+
aiAnnotator: {
|
|
86
|
+
port: 7318,
|
|
87
|
+
autoSetupMcp: true,
|
|
88
|
+
verbose: false,
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**That's it!** Nuxt handles the rest automatically.
|
|
94
|
+
|
|
95
|
+
#### Configure MCP (Vite and Nuxt)
|
|
67
96
|
|
|
68
97
|
**Option A: Auto Setup (Recommended)**
|
|
69
98
|
|
|
@@ -75,6 +104,17 @@ annotator({
|
|
|
75
104
|
})
|
|
76
105
|
```
|
|
77
106
|
|
|
107
|
+
For Nuxt, configure in `nuxt.config.ts`:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
export default defineNuxtConfig({
|
|
111
|
+
modules: ['vite-plugin-ai-annotator/nuxt'],
|
|
112
|
+
aiAnnotator: {
|
|
113
|
+
autoSetupMcp: true,
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
```
|
|
117
|
+
|
|
78
118
|
This automatically creates/updates `.mcp.json`, `.cursor/mcp.json`, and `.vscode/mcp.json` based on your project.
|
|
79
119
|
|
|
80
120
|
**Option B: Manual Setup**
|
|
@@ -83,7 +123,7 @@ This automatically creates/updates `.mcp.json`, `.cursor/mcp.json`, and `.vscode
|
|
|
83
123
|
claude mcp add annotator -- npx vite-plugin-ai-annotator mcp -s http://localhost:7318
|
|
84
124
|
```
|
|
85
125
|
|
|
86
|
-
#### Step
|
|
126
|
+
#### Step 3: Start your dev server
|
|
87
127
|
|
|
88
128
|
```bash
|
|
89
129
|
bun dev
|
|
@@ -6389,10 +6389,15 @@
|
|
|
6389
6389
|
// src/annotator/constants.ts
|
|
6390
6390
|
var Z_INDEX = {
|
|
6391
6391
|
INSPECTION_OVERLAY: 999995,
|
|
6392
|
+
// Mouse inspection hover highlight
|
|
6392
6393
|
HIGHLIGHT_OVERLAY: 999996,
|
|
6394
|
+
// Selected element marching ants border
|
|
6393
6395
|
HOVER_OVERLAY: 999997,
|
|
6396
|
+
// Element hover during inspection mode
|
|
6394
6397
|
BADGE: 999998,
|
|
6398
|
+
// Selection badge with index number
|
|
6395
6399
|
TOOLBAR: 999999
|
|
6400
|
+
// Bottom-right toolbar UI
|
|
6396
6401
|
};
|
|
6397
6402
|
var CONSOLE_LIMITS = {
|
|
6398
6403
|
MAX_ARG_LENGTH: 1e4,
|
|
@@ -7216,14 +7221,17 @@
|
|
|
7216
7221
|
let vnode = null;
|
|
7217
7222
|
if (!codeLocation) {
|
|
7218
7223
|
const ctxVNode = el.__vnode?.ctx?.vnode;
|
|
7219
|
-
if (ctxVNode
|
|
7220
|
-
codeLocation = ctxVNode
|
|
7224
|
+
if (ctxVNode && ctxVNode.el === element) {
|
|
7225
|
+
codeLocation = ctxVNode.props?.__v_inspector;
|
|
7221
7226
|
}
|
|
7222
7227
|
}
|
|
7223
7228
|
if (!codeLocation) {
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7229
|
+
const parentComponent = el.__vueParentComponent;
|
|
7230
|
+
if (parentComponent?.vnode) {
|
|
7231
|
+
codeLocation = parentComponent.vnode.props?.__v_inspector;
|
|
7232
|
+
vueInstance = parentComponent;
|
|
7233
|
+
vnode = parentComponent.vnode;
|
|
7234
|
+
}
|
|
7227
7235
|
}
|
|
7228
7236
|
if (!codeLocation) {
|
|
7229
7237
|
codeLocation = el.__v_inspector;
|
|
@@ -7516,6 +7524,7 @@
|
|
|
7516
7524
|
this.tooltipCleanup = null;
|
|
7517
7525
|
this.toastTimeout = null;
|
|
7518
7526
|
this.clickListenerTimeout = null;
|
|
7527
|
+
this.skipNextClickOutside = false;
|
|
7519
7528
|
this.socket = null;
|
|
7520
7529
|
this.rpc = null;
|
|
7521
7530
|
this.selectionManager = null;
|
|
@@ -7533,6 +7542,10 @@
|
|
|
7533
7542
|
};
|
|
7534
7543
|
this.handleClickOutside = (e5) => {
|
|
7535
7544
|
if (!this.commentPopover.visible) return;
|
|
7545
|
+
if (this.skipNextClickOutside) {
|
|
7546
|
+
this.skipNextClickOutside = false;
|
|
7547
|
+
return;
|
|
7548
|
+
}
|
|
7536
7549
|
const popoverEl = this.shadowRoot?.querySelector(".popover");
|
|
7537
7550
|
if (!popoverEl) return;
|
|
7538
7551
|
const path = e5.composedPath();
|
|
@@ -7566,29 +7579,36 @@
|
|
|
7566
7579
|
}
|
|
7567
7580
|
initializeConsoleCapture() {
|
|
7568
7581
|
try {
|
|
7582
|
+
const originals = {};
|
|
7569
7583
|
CONSOLE_METHODS.forEach((method) => {
|
|
7570
|
-
|
|
7584
|
+
originals[method] = console[method].bind(console);
|
|
7571
7585
|
});
|
|
7572
7586
|
CONSOLE_METHODS.forEach((method) => {
|
|
7573
7587
|
console[method] = (...args) => {
|
|
7574
|
-
|
|
7575
|
-
|
|
7576
|
-
args: args.map((arg) => {
|
|
7588
|
+
try {
|
|
7589
|
+
const serializedArgs = args.map((arg) => {
|
|
7577
7590
|
try {
|
|
7578
7591
|
const str = typeof arg === "object" ? JSON.stringify(arg) : String(arg);
|
|
7579
7592
|
return str.length > CONSOLE_LIMITS.MAX_ARG_LENGTH ? str.slice(0, CONSOLE_LIMITS.MAX_ARG_LENGTH) + "...[truncated]" : str;
|
|
7580
7593
|
} catch {
|
|
7581
7594
|
return "[circular or unserializable]";
|
|
7582
7595
|
}
|
|
7583
|
-
})
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7596
|
+
});
|
|
7597
|
+
this.consoleBuffer.push({
|
|
7598
|
+
type: method,
|
|
7599
|
+
args: serializedArgs,
|
|
7600
|
+
timestamp: Date.now()
|
|
7601
|
+
});
|
|
7602
|
+
if (this.consoleBuffer.length > CONSOLE_LIMITS.BUFFER_MAX) {
|
|
7603
|
+
this.consoleBuffer = this.consoleBuffer.slice(-CONSOLE_LIMITS.BUFFER_TRIM_TO);
|
|
7604
|
+
}
|
|
7605
|
+
originals[method]?.(...args);
|
|
7606
|
+
} catch (captureError) {
|
|
7607
|
+
originals[method]?.(...args);
|
|
7588
7608
|
}
|
|
7589
|
-
this.originalConsoleMethods[method]?.(...args);
|
|
7590
7609
|
};
|
|
7591
7610
|
});
|
|
7611
|
+
this.originalConsoleMethods = originals;
|
|
7592
7612
|
} catch (error) {
|
|
7593
7613
|
this.restoreConsoleMethods();
|
|
7594
7614
|
throw error;
|
|
@@ -7630,19 +7650,71 @@
|
|
|
7630
7650
|
}
|
|
7631
7651
|
registerRpcHandlers() {
|
|
7632
7652
|
if (!this.rpc) return;
|
|
7633
|
-
this.rpc.handle.getPageContext(async () =>
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
);
|
|
7641
|
-
this.rpc.handle.
|
|
7653
|
+
this.rpc.handle.getPageContext(async () => {
|
|
7654
|
+
try {
|
|
7655
|
+
return await this.getPageContext();
|
|
7656
|
+
} catch (error) {
|
|
7657
|
+
this.log("[getPageContext] Handler error:", error);
|
|
7658
|
+
throw { message: error instanceof Error ? error.message : String(error), code: "INTERNAL_ERROR", data: void 0 };
|
|
7659
|
+
}
|
|
7660
|
+
});
|
|
7661
|
+
this.rpc.handle.getSelectedElements(async () => {
|
|
7662
|
+
try {
|
|
7663
|
+
return await this.getSelectedElements();
|
|
7664
|
+
} catch (error) {
|
|
7665
|
+
this.log("[getSelectedElements] Handler error:", error);
|
|
7666
|
+
throw { message: error instanceof Error ? error.message : String(error), code: "INTERNAL_ERROR", data: void 0 };
|
|
7667
|
+
}
|
|
7668
|
+
});
|
|
7669
|
+
this.rpc.handle.triggerSelection(async (mode, selector, selectorType) => {
|
|
7670
|
+
try {
|
|
7671
|
+
return await this.triggerSelection(mode, selector, selectorType);
|
|
7672
|
+
} catch (error) {
|
|
7673
|
+
this.log("[triggerSelection] Handler error:", error);
|
|
7674
|
+
throw { message: error instanceof Error ? error.message : String(error), code: "INTERNAL_ERROR", data: void 0 };
|
|
7675
|
+
}
|
|
7676
|
+
});
|
|
7677
|
+
this.rpc.handle.captureScreenshot(async (type, selector, quality) => {
|
|
7678
|
+
try {
|
|
7679
|
+
return await this.captureScreenshot(type, selector, quality);
|
|
7680
|
+
} catch (error) {
|
|
7681
|
+
this.log("[captureScreenshot] Handler error:", error);
|
|
7682
|
+
throw { message: error instanceof Error ? error.message : String(error), code: "INTERNAL_ERROR", data: void 0 };
|
|
7683
|
+
}
|
|
7684
|
+
});
|
|
7685
|
+
this.rpc.handle.clearSelection(async () => {
|
|
7686
|
+
try {
|
|
7687
|
+
return await this.clearSelection();
|
|
7688
|
+
} catch (error) {
|
|
7689
|
+
this.log("[clearSelection] Handler error:", error);
|
|
7690
|
+
throw { message: error instanceof Error ? error.message : String(error), code: "INTERNAL_ERROR", data: void 0 };
|
|
7691
|
+
}
|
|
7692
|
+
});
|
|
7642
7693
|
this.rpc.handle.ping(async () => "pong");
|
|
7643
|
-
this.rpc.handle.injectCSS(async (css) =>
|
|
7644
|
-
|
|
7645
|
-
|
|
7694
|
+
this.rpc.handle.injectCSS(async (css) => {
|
|
7695
|
+
try {
|
|
7696
|
+
return await this.injectCSS(css);
|
|
7697
|
+
} catch (error) {
|
|
7698
|
+
this.log("[injectCSS] Handler error:", error);
|
|
7699
|
+
throw { message: error instanceof Error ? error.message : String(error), code: "INTERNAL_ERROR", data: void 0 };
|
|
7700
|
+
}
|
|
7701
|
+
});
|
|
7702
|
+
this.rpc.handle.injectJS(async (code) => {
|
|
7703
|
+
try {
|
|
7704
|
+
return await this.injectJS(code);
|
|
7705
|
+
} catch (error) {
|
|
7706
|
+
this.log("[injectJS] Handler error:", error);
|
|
7707
|
+
throw { message: error instanceof Error ? error.message : String(error), code: "INTERNAL_ERROR", data: void 0 };
|
|
7708
|
+
}
|
|
7709
|
+
});
|
|
7710
|
+
this.rpc.handle.getConsole(async (clear) => {
|
|
7711
|
+
try {
|
|
7712
|
+
return await this.getConsoleLogs(clear);
|
|
7713
|
+
} catch (error) {
|
|
7714
|
+
this.log("[getConsole] Handler error:", error);
|
|
7715
|
+
throw { message: error instanceof Error ? error.message : String(error), code: "INTERNAL_ERROR", data: void 0 };
|
|
7716
|
+
}
|
|
7717
|
+
});
|
|
7646
7718
|
}
|
|
7647
7719
|
reportPageContext() {
|
|
7648
7720
|
if (!this.socket?.connected) return;
|
|
@@ -7744,10 +7816,12 @@
|
|
|
7744
7816
|
cacheBust: true,
|
|
7745
7817
|
pixelRatio: 1,
|
|
7746
7818
|
includeQueryParams: true,
|
|
7747
|
-
// Filter out
|
|
7819
|
+
// Filter out all annotator UI elements
|
|
7748
7820
|
filter: (node) => {
|
|
7749
7821
|
if (node instanceof Element) {
|
|
7750
|
-
|
|
7822
|
+
const className = node.className || "";
|
|
7823
|
+
const tagName = node.tagName?.toLowerCase() || "";
|
|
7824
|
+
if (className.includes("annotator-") || tagName === "annotator-toolbar") {
|
|
7751
7825
|
return false;
|
|
7752
7826
|
}
|
|
7753
7827
|
}
|
|
@@ -7878,6 +7952,7 @@
|
|
|
7878
7952
|
if (this.clickListenerTimeout) {
|
|
7879
7953
|
clearTimeout(this.clickListenerTimeout);
|
|
7880
7954
|
}
|
|
7955
|
+
this.skipNextClickOutside = true;
|
|
7881
7956
|
this.clickListenerTimeout = setTimeout(() => {
|
|
7882
7957
|
document.addEventListener("click", this.handleClickOutside, true);
|
|
7883
7958
|
this.clickListenerTimeout = null;
|
|
@@ -7931,6 +8006,9 @@
|
|
|
7931
8006
|
this.popoverCleanup();
|
|
7932
8007
|
this.popoverCleanup = null;
|
|
7933
8008
|
}
|
|
8009
|
+
const popoverEl = this.shadowRoot?.querySelector(".popover");
|
|
8010
|
+
if (popoverEl) {
|
|
8011
|
+
}
|
|
7934
8012
|
this.commentPopover = { visible: false, element: null, comment: "" };
|
|
7935
8013
|
}
|
|
7936
8014
|
handlePopoverInput(e5) {
|
|
@@ -8136,7 +8214,7 @@
|
|
|
8136
8214
|
render() {
|
|
8137
8215
|
if (!this.connected) {
|
|
8138
8216
|
return x`
|
|
8139
|
-
<div class="toolbar">
|
|
8217
|
+
<div class="toolbar" role="alert" aria-live="polite">
|
|
8140
8218
|
<div class="error-message">
|
|
8141
8219
|
${this.renderErrorIcon()}
|
|
8142
8220
|
<span>Cannot connect to AI Annotator server</span>
|
|
@@ -8145,12 +8223,15 @@
|
|
|
8145
8223
|
`;
|
|
8146
8224
|
}
|
|
8147
8225
|
return x`
|
|
8148
|
-
<div class="toolbar">
|
|
8226
|
+
<div class="toolbar" role="toolbar" aria-label="AI Annotator tools">
|
|
8149
8227
|
<button
|
|
8150
8228
|
class="toolbar-btn ${this.isInspecting ? "active" : ""}"
|
|
8151
8229
|
@click=${this.toggleInspect}
|
|
8152
8230
|
@mouseenter=${(e5) => this.showTooltip(this.isInspecting ? "Press ESC to exit" : "Inspect elements", e5.currentTarget)}
|
|
8153
8231
|
@mouseleave=${() => this.hideTooltip()}
|
|
8232
|
+
aria-label="${this.isInspecting ? "Exit inspection mode" : "Inspect elements"}"
|
|
8233
|
+
aria-pressed="${this.isInspecting}"
|
|
8234
|
+
title="${this.isInspecting ? "Press ESC to exit" : "Inspect elements"}"
|
|
8154
8235
|
>
|
|
8155
8236
|
${this.renderCursorIcon()}
|
|
8156
8237
|
</button>
|
|
@@ -8162,19 +8243,24 @@
|
|
|
8162
8243
|
@mouseenter=${(e5) => this.showTooltip("Clear selections", e5.currentTarget)}
|
|
8163
8244
|
@mouseleave=${() => this.hideTooltip()}
|
|
8164
8245
|
?disabled=${this.selectionCount === 0}
|
|
8246
|
+
aria-label="Clear all selections"
|
|
8247
|
+
aria-disabled="${this.selectionCount === 0}"
|
|
8248
|
+
title="Clear selections"
|
|
8165
8249
|
>
|
|
8166
8250
|
${this.renderTrashIcon()}
|
|
8167
8251
|
</button>
|
|
8168
|
-
${this.selectionCount > 0 ? x`<span class="badge">${this.selectionCount}</span>` : ""}
|
|
8252
|
+
${this.selectionCount > 0 ? x`<span class="badge" aria-label="${this.selectionCount} selections">${this.selectionCount}</span>` : ""}
|
|
8169
8253
|
</div>
|
|
8170
8254
|
|
|
8171
|
-
<div class="divider"></div>
|
|
8255
|
+
<div class="divider" role="separator" aria-orientation="vertical"></div>
|
|
8172
8256
|
|
|
8173
8257
|
<button
|
|
8174
8258
|
class="toolbar-btn"
|
|
8175
8259
|
@click=${this.copySessionId}
|
|
8176
8260
|
@mouseenter=${(e5) => this.showTooltip("Copy session", e5.currentTarget)}
|
|
8177
8261
|
@mouseleave=${() => this.hideTooltip()}
|
|
8262
|
+
aria-label="Copy session ID to clipboard"
|
|
8263
|
+
title="Copy session"
|
|
8178
8264
|
>
|
|
8179
8265
|
${this.renderClipboardIcon()}
|
|
8180
8266
|
</button>
|
|
@@ -8184,17 +8270,19 @@
|
|
|
8184
8270
|
@click=${this.openHelpPage}
|
|
8185
8271
|
@mouseenter=${(e5) => this.showTooltip("Help", e5.currentTarget)}
|
|
8186
8272
|
@mouseleave=${() => this.hideTooltip()}
|
|
8273
|
+
aria-label="Open help documentation"
|
|
8274
|
+
title="Help"
|
|
8187
8275
|
>
|
|
8188
8276
|
${this.renderHelpIcon()}
|
|
8189
8277
|
</button>
|
|
8190
8278
|
|
|
8191
|
-
${this.toastMessage ? x`<div class="toast">${this.toastMessage}</div>` : ""}
|
|
8279
|
+
${this.toastMessage ? x`<div class="toast" role="status" aria-live="polite">${this.toastMessage}</div>` : ""}
|
|
8192
8280
|
</div>
|
|
8193
8281
|
|
|
8194
|
-
${this.tooltip.visible ? x`<div class="tooltip">${this.tooltip.text}</div>` : ""}
|
|
8282
|
+
${this.tooltip.visible ? x`<div class="tooltip" role="tooltip">${this.tooltip.text}</div>` : ""}
|
|
8195
8283
|
|
|
8196
8284
|
${this.commentPopover.visible ? x`
|
|
8197
|
-
<div class="popover">
|
|
8285
|
+
<div class="popover" role="dialog" aria-label="Element comment" aria-modal="false">
|
|
8198
8286
|
<textarea
|
|
8199
8287
|
class="popover-input"
|
|
8200
8288
|
placeholder="Add a note... (↵ to close)"
|
|
@@ -8202,12 +8290,13 @@
|
|
|
8202
8290
|
@input=${this.handlePopoverInput}
|
|
8203
8291
|
@keydown=${this.handlePopoverInputKeydown}
|
|
8204
8292
|
rows="1"
|
|
8293
|
+
aria-label="Add a comment for the selected element"
|
|
8205
8294
|
></textarea>
|
|
8206
|
-
<div class="popover-actions">
|
|
8207
|
-
<button class="popover-btn danger" @click=${this.removeSelectedElement} title="Remove selection">
|
|
8295
|
+
<div class="popover-actions" role="group" aria-label="Comment actions">
|
|
8296
|
+
<button class="popover-btn danger" @click=${this.removeSelectedElement} title="Remove selection" aria-label="Remove this selection">
|
|
8208
8297
|
${this.renderTrashIcon()}
|
|
8209
8298
|
</button>
|
|
8210
|
-
<button class="popover-btn" @click=${this.hideCommentPopover} title="Close (Esc)">
|
|
8299
|
+
<button class="popover-btn" @click=${this.hideCommentPopover} title="Close (Esc)" aria-label="Close comment">
|
|
8211
8300
|
${this.renderCloseIcon()}
|
|
8212
8301
|
</button>
|
|
8213
8302
|
</div>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type AiAnnotatorOptions } from './vite-plugin';
|
|
2
|
+
export interface NuxtAiAnnotatorOptions extends AiAnnotatorOptions {
|
|
3
|
+
}
|
|
4
|
+
declare const _default: import("@nuxt/schema").NuxtModule<NuxtAiAnnotatorOptions, NuxtAiAnnotatorOptions, false>;
|
|
5
|
+
export default _default;
|