@akccakcctw/vue-grab 1.0.0 → 1.3.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/dist/core/api.d.ts +28 -0
- package/dist/core/api.js +105 -0
- package/dist/core/identifier.d.ts +2 -0
- package/dist/core/identifier.js +101 -0
- package/dist/core/overlay.d.ts +24 -0
- package/dist/core/overlay.js +509 -0
- package/dist/core/widget.d.ts +10 -0
- package/dist/core/widget.js +251 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +7 -0
- package/dist/nuxt/module.d.ts +8 -0
- package/dist/nuxt/module.js +40 -0
- package/dist/nuxt/runtime/plugin.d.ts +2 -0
- package/dist/nuxt/runtime/plugin.js +14 -0
- package/dist/plugin.d.ts +11 -0
- package/dist/plugin.js +47 -0
- package/dist/vite.d.ts +8 -0
- package/dist/vite.js +198 -0
- package/package.json +33 -8
- package/.github/release-please-config.json +0 -9
- package/.github/release-please-manifest.json +0 -3
- package/.github/workflows/release.yml +0 -37
- package/AGENTS.md +0 -75
- package/README.md +0 -116
- package/akccakcctw-vue-grab-1.0.0.tgz +0 -0
- package/docs/SDD.md +0 -188
- package/src/__tests__/plugin.spec.ts +0 -60
- package/src/core/__tests__/api.spec.ts +0 -178
- package/src/core/__tests__/identifier.spec.ts +0 -126
- package/src/core/__tests__/overlay.spec.ts +0 -431
- package/src/core/__tests__/widget.spec.ts +0 -57
- package/src/core/api.ts +0 -144
- package/src/core/identifier.ts +0 -89
- package/src/core/overlay.ts +0 -348
- package/src/core/widget.ts +0 -289
- package/src/index.ts +0 -8
- package/src/nuxt/module.ts +0 -102
- package/src/nuxt/runtime/plugin.ts +0 -13
- package/src/plugin.ts +0 -48
- package/tsconfig.json +0 -44
- package/vitest.config.ts +0 -9
package/src/core/widget.ts
DELETED
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
type ToggleWidgetOptions = {
|
|
2
|
-
onToggle: (nextActive: boolean) => void;
|
|
3
|
-
};
|
|
4
|
-
|
|
5
|
-
type ToggleWidgetController = {
|
|
6
|
-
mount: () => void;
|
|
7
|
-
unmount: () => void;
|
|
8
|
-
setActive: (active: boolean) => void;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type DragState = {
|
|
12
|
-
dragging: boolean;
|
|
13
|
-
offsetX: number;
|
|
14
|
-
offsetY: number;
|
|
15
|
-
moved: boolean;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const CURSOR_ICON = `<svg data-v-6fdbd1c9="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="height: 1.2em; width: 1.2em; pointer-events: none;"><g data-v-6fdbd1c9="" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><circle data-v-6fdbd1c9="" cx="12" cy="12" r=".5" fill="currentColor"></circle><path data-v-6fdbd1c9="" d="M5 12a7 7 0 1 0 14 0a7 7 0 1 0-14 0m7-9v2m-9 7h2m7 7v2m7-9h2"></path></g></svg>`;
|
|
19
|
-
const CHEVRON_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" width="12" height="12" style="transform: rotate(180deg); pointer-events: none;"><path d="m18 15-6-6-6 6"></path></svg>`;
|
|
20
|
-
|
|
21
|
-
function createToolbar(targetWindow: Window) {
|
|
22
|
-
const doc = targetWindow.document;
|
|
23
|
-
const container = doc.createElement('div');
|
|
24
|
-
|
|
25
|
-
// Outer Container Styles
|
|
26
|
-
Object.assign(container.style, {
|
|
27
|
-
position: 'fixed',
|
|
28
|
-
left: '16px',
|
|
29
|
-
top: '16px',
|
|
30
|
-
zIndex: '2147483647',
|
|
31
|
-
fontFamily: 'sans-serif',
|
|
32
|
-
fontSize: '13px',
|
|
33
|
-
userSelect: 'none',
|
|
34
|
-
cursor: 'grab',
|
|
35
|
-
filter: 'drop-shadow(0px 0px 4px rgba(81, 81, 81, 0.5))',
|
|
36
|
-
transition: 'opacity 300ms ease-out, padding 0.2s ease',
|
|
37
|
-
opacity: '1',
|
|
38
|
-
});
|
|
39
|
-
container.setAttribute('data-vue-grab-toolbar', '');
|
|
40
|
-
container.setAttribute('data-vue-grab-ignore-events', '');
|
|
41
|
-
|
|
42
|
-
const inner = doc.createElement('div');
|
|
43
|
-
Object.assign(inner.style, {
|
|
44
|
-
display: 'flex',
|
|
45
|
-
alignItems: 'center',
|
|
46
|
-
justifyContent: 'center',
|
|
47
|
-
borderRadius: '4px',
|
|
48
|
-
backgroundColor: 'white',
|
|
49
|
-
gap: '6px',
|
|
50
|
-
padding: '6px 8px',
|
|
51
|
-
transition: 'gap 0.2s ease, padding 0.2s ease',
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Toggle Button Wrapper
|
|
55
|
-
const toggleWrapper = doc.createElement('div');
|
|
56
|
-
Object.assign(toggleWrapper.style, {
|
|
57
|
-
display: 'flex',
|
|
58
|
-
alignItems: 'center',
|
|
59
|
-
gap: '6px',
|
|
60
|
-
overflow: 'hidden',
|
|
61
|
-
maxWidth: '200px',
|
|
62
|
-
transition: 'max-width 0.2s ease, opacity 0.2s ease'
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// Toggle Button
|
|
66
|
-
const toggleBtn = doc.createElement('button');
|
|
67
|
-
toggleBtn.setAttribute('data-vue-grab-toggle', '');
|
|
68
|
-
Object.assign(toggleBtn.style, {
|
|
69
|
-
display: 'flex',
|
|
70
|
-
alignItems: 'center',
|
|
71
|
-
justifyContent: 'center',
|
|
72
|
-
cursor: 'pointer',
|
|
73
|
-
border: 'none',
|
|
74
|
-
background: 'transparent',
|
|
75
|
-
padding: '0',
|
|
76
|
-
transition: 'transform 0.1s',
|
|
77
|
-
color: 'rgba(0, 0, 0, 0.7)'
|
|
78
|
-
});
|
|
79
|
-
toggleBtn.innerHTML = CURSOR_ICON;
|
|
80
|
-
toggleBtn.onmouseenter = () => toggleBtn.style.transform = 'scale(1.05)';
|
|
81
|
-
toggleBtn.onmouseleave = () => toggleBtn.style.transform = 'scale(1)';
|
|
82
|
-
|
|
83
|
-
toggleWrapper.appendChild(toggleBtn);
|
|
84
|
-
|
|
85
|
-
// Collapse Button
|
|
86
|
-
const collapseBtn = doc.createElement('button');
|
|
87
|
-
collapseBtn.setAttribute('data-vue-grab-collapse', '');
|
|
88
|
-
Object.assign(collapseBtn.style, {
|
|
89
|
-
display: 'flex',
|
|
90
|
-
alignItems: 'center',
|
|
91
|
-
justifyContent: 'center',
|
|
92
|
-
cursor: 'pointer',
|
|
93
|
-
border: 'none',
|
|
94
|
-
background: 'transparent',
|
|
95
|
-
padding: '0',
|
|
96
|
-
transition: 'transform 0.1s',
|
|
97
|
-
color: '#B3B3B3'
|
|
98
|
-
});
|
|
99
|
-
collapseBtn.innerHTML = CHEVRON_ICON;
|
|
100
|
-
collapseBtn.onmouseenter = () => collapseBtn.style.transform = 'scale(1.05)';
|
|
101
|
-
collapseBtn.onmouseleave = () => collapseBtn.style.transform = 'scale(1)';
|
|
102
|
-
|
|
103
|
-
inner.appendChild(toggleWrapper);
|
|
104
|
-
inner.appendChild(collapseBtn);
|
|
105
|
-
container.appendChild(inner);
|
|
106
|
-
|
|
107
|
-
return { container, toggleBtn, collapseBtn, toggleWrapper };
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function setButtonState(toggleBtn: HTMLElement, active: boolean) {
|
|
111
|
-
// Use color to indicate state: Blue for active, Gray for inactive
|
|
112
|
-
toggleBtn.style.color = active ? '#3b82f6' : 'rgba(0, 0, 0, 0.7)';
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export function createToggleWidget(
|
|
116
|
-
targetWindow: Window,
|
|
117
|
-
options: ToggleWidgetOptions
|
|
118
|
-
): ToggleWidgetController {
|
|
119
|
-
let elements:
|
|
120
|
-
| {
|
|
121
|
-
container: HTMLDivElement;
|
|
122
|
-
toggleBtn: HTMLButtonElement;
|
|
123
|
-
collapseBtn: HTMLButtonElement;
|
|
124
|
-
toggleWrapper: HTMLDivElement;
|
|
125
|
-
}
|
|
126
|
-
| null = null;
|
|
127
|
-
let mounted = false;
|
|
128
|
-
let isActive = false;
|
|
129
|
-
let isCollapsed = false;
|
|
130
|
-
let lastPosition = {
|
|
131
|
-
left: '',
|
|
132
|
-
top: '',
|
|
133
|
-
right: '',
|
|
134
|
-
bottom: ''
|
|
135
|
-
};
|
|
136
|
-
const defaultInnerGap = '6px';
|
|
137
|
-
const defaultInnerPadding = '6px 8px';
|
|
138
|
-
const dragState: DragState = {
|
|
139
|
-
dragging: false,
|
|
140
|
-
offsetX: 0,
|
|
141
|
-
offsetY: 0,
|
|
142
|
-
moved: false
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const startDrag = (event: MouseEvent) => {
|
|
146
|
-
if (!elements) return;
|
|
147
|
-
// Don't drag if clicking buttons directly might be better handled by stopPropagation,
|
|
148
|
-
// but here we allow dragging from anywhere on the container.
|
|
149
|
-
// However, if we click a button, we might want to prevent drag start or ensure click works?
|
|
150
|
-
// Usually standard behavior: mousedown + mouseup without move = click. mousedown + move = drag.
|
|
151
|
-
|
|
152
|
-
dragState.dragging = true;
|
|
153
|
-
dragState.moved = false;
|
|
154
|
-
const rect = elements.container.getBoundingClientRect();
|
|
155
|
-
dragState.offsetX = event.clientX - rect.left;
|
|
156
|
-
dragState.offsetY = event.clientY - rect.top;
|
|
157
|
-
|
|
158
|
-
// Switch to explicit coords for dragging
|
|
159
|
-
elements.container.style.right = 'auto';
|
|
160
|
-
elements.container.style.bottom = 'auto';
|
|
161
|
-
elements.container.style.left = `${rect.left}px`;
|
|
162
|
-
elements.container.style.top = `${rect.top}px`;
|
|
163
|
-
elements.container.style.cursor = 'grabbing';
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
const onDrag = (event: MouseEvent) => {
|
|
167
|
-
if (!elements || !dragState.dragging) return;
|
|
168
|
-
dragState.moved = true;
|
|
169
|
-
const nextLeft = event.clientX - dragState.offsetX;
|
|
170
|
-
const nextTop = event.clientY - dragState.offsetY;
|
|
171
|
-
const maxLeft = targetWindow.innerWidth - elements.container.offsetWidth;
|
|
172
|
-
const maxTop = targetWindow.innerHeight - elements.container.offsetHeight;
|
|
173
|
-
const clampedLeft = Math.max(0, Math.min(maxLeft, nextLeft));
|
|
174
|
-
const clampedTop = Math.max(0, Math.min(maxTop, nextTop));
|
|
175
|
-
elements.container.style.left = `${clampedLeft}px`;
|
|
176
|
-
elements.container.style.top = `${clampedTop}px`;
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const endDrag = () => {
|
|
180
|
-
if (!elements) return;
|
|
181
|
-
dragState.dragging = false;
|
|
182
|
-
elements.container.style.cursor = 'grab';
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
const toggleCollapse = () => {
|
|
186
|
-
if (!elements) return;
|
|
187
|
-
const { container, toggleWrapper, collapseBtn } = elements;
|
|
188
|
-
const inner = container.firstElementChild as HTMLDivElement | null;
|
|
189
|
-
const svg = collapseBtn.querySelector('svg') as SVGElement | null;
|
|
190
|
-
|
|
191
|
-
if (!isCollapsed) {
|
|
192
|
-
const rect = container.getBoundingClientRect();
|
|
193
|
-
lastPosition = {
|
|
194
|
-
left: container.style.left,
|
|
195
|
-
top: container.style.top,
|
|
196
|
-
right: container.style.right,
|
|
197
|
-
bottom: container.style.bottom
|
|
198
|
-
};
|
|
199
|
-
const stickLeft = rect.left + rect.width / 2 < targetWindow.innerWidth / 2;
|
|
200
|
-
container.style.top = `${rect.top}px`;
|
|
201
|
-
if (stickLeft) {
|
|
202
|
-
container.style.left = '0px';
|
|
203
|
-
container.style.right = 'auto';
|
|
204
|
-
} else {
|
|
205
|
-
container.style.left = 'auto';
|
|
206
|
-
container.style.right = '0px';
|
|
207
|
-
}
|
|
208
|
-
container.style.bottom = 'auto';
|
|
209
|
-
container.style.transform = 'scale(0.8)';
|
|
210
|
-
container.style.padding = '0';
|
|
211
|
-
toggleWrapper.style.maxWidth = '0px';
|
|
212
|
-
toggleWrapper.style.opacity = '0';
|
|
213
|
-
toggleWrapper.style.pointerEvents = 'none';
|
|
214
|
-
if (inner) {
|
|
215
|
-
inner.style.gap = '0';
|
|
216
|
-
inner.style.padding = '6px';
|
|
217
|
-
}
|
|
218
|
-
if (svg) svg.style.transform = 'rotate(0deg)';
|
|
219
|
-
isCollapsed = true;
|
|
220
|
-
} else {
|
|
221
|
-
container.style.left = lastPosition.left;
|
|
222
|
-
container.style.top = lastPosition.top;
|
|
223
|
-
container.style.right = lastPosition.right;
|
|
224
|
-
container.style.bottom = lastPosition.bottom;
|
|
225
|
-
container.style.transform = 'scale(1)';
|
|
226
|
-
container.style.padding = '';
|
|
227
|
-
toggleWrapper.style.maxWidth = '200px';
|
|
228
|
-
toggleWrapper.style.opacity = '1';
|
|
229
|
-
toggleWrapper.style.pointerEvents = 'auto';
|
|
230
|
-
if (inner) {
|
|
231
|
-
inner.style.gap = defaultInnerGap;
|
|
232
|
-
inner.style.padding = defaultInnerPadding;
|
|
233
|
-
}
|
|
234
|
-
if (svg) svg.style.transform = 'rotate(180deg)';
|
|
235
|
-
isCollapsed = false;
|
|
236
|
-
}
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
return {
|
|
240
|
-
mount() {
|
|
241
|
-
if (mounted) return;
|
|
242
|
-
mounted = true;
|
|
243
|
-
elements = createToolbar(targetWindow);
|
|
244
|
-
if (!elements) return;
|
|
245
|
-
|
|
246
|
-
setButtonState(elements.toggleBtn, isActive);
|
|
247
|
-
|
|
248
|
-
// Drag listeners on the container
|
|
249
|
-
elements.container.addEventListener('mousedown', startDrag);
|
|
250
|
-
|
|
251
|
-
// Toggle logic
|
|
252
|
-
elements.toggleBtn.addEventListener('click', (event) => {
|
|
253
|
-
event.preventDefault();
|
|
254
|
-
event.stopPropagation(); // Prevent affecting container?
|
|
255
|
-
if (dragState.moved) return; // Prevent toggle if it was a drag
|
|
256
|
-
|
|
257
|
-
isActive = !isActive;
|
|
258
|
-
setButtonState(elements!.toggleBtn, isActive);
|
|
259
|
-
options.onToggle(isActive);
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
// Collapse logic (Placeholder)
|
|
263
|
-
elements.collapseBtn.addEventListener('click', (event) => {
|
|
264
|
-
event.preventDefault();
|
|
265
|
-
event.stopPropagation();
|
|
266
|
-
if (dragState.moved) return;
|
|
267
|
-
toggleCollapse();
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
targetWindow.addEventListener('mousemove', onDrag);
|
|
271
|
-
targetWindow.addEventListener('mouseup', endDrag);
|
|
272
|
-
targetWindow.document.body.appendChild(elements.container);
|
|
273
|
-
},
|
|
274
|
-
unmount() {
|
|
275
|
-
if (!mounted || !elements) return;
|
|
276
|
-
mounted = false;
|
|
277
|
-
elements.container.removeEventListener('mousedown', startDrag);
|
|
278
|
-
elements.container.remove();
|
|
279
|
-
elements = null;
|
|
280
|
-
targetWindow.removeEventListener('mousemove', onDrag);
|
|
281
|
-
targetWindow.removeEventListener('mouseup', endDrag);
|
|
282
|
-
},
|
|
283
|
-
setActive(active: boolean) {
|
|
284
|
-
isActive = active;
|
|
285
|
-
if (!elements) return;
|
|
286
|
-
setButtonState(elements.toggleBtn, active);
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { createVueGrabAPI, installVueGrab } from './core/api';
|
|
2
|
-
export type { VueGrabOptions } from './core/api';
|
|
3
|
-
export type { OverlayOptions, OverlayStyle } from './core/overlay';
|
|
4
|
-
export { createToggleWidget } from './core/widget';
|
|
5
|
-
export { identifyComponent, extractMetadata } from './core/identifier';
|
|
6
|
-
export { createOverlayController } from './core/overlay';
|
|
7
|
-
export { createVueGrabPlugin } from './plugin';
|
|
8
|
-
export { default } from './plugin';
|
package/src/nuxt/module.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { addPlugin, createResolver, defineNuxtModule, addVitePlugin } from '@nuxt/kit';
|
|
2
|
-
|
|
3
|
-
export type VueGrabNuxtModuleOptions = {
|
|
4
|
-
enabled?: boolean;
|
|
5
|
-
overlayStyle?: Record<string, string>;
|
|
6
|
-
copyOnClick?: boolean;
|
|
7
|
-
rootDir?: string;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export default defineNuxtModule<VueGrabNuxtModuleOptions>({
|
|
11
|
-
meta: {
|
|
12
|
-
name: 'vue-grab',
|
|
13
|
-
configKey: 'vueGrab'
|
|
14
|
-
},
|
|
15
|
-
defaults: {
|
|
16
|
-
enabled: true
|
|
17
|
-
},
|
|
18
|
-
setup(options, nuxt) {
|
|
19
|
-
if (options.enabled === false) return;
|
|
20
|
-
const shouldEnable = nuxt.options.dev || options.enabled === true;
|
|
21
|
-
if (!shouldEnable) return;
|
|
22
|
-
|
|
23
|
-
const publicConfig = (nuxt.options.runtimeConfig.public ||= {});
|
|
24
|
-
const { enabled, overlayStyle, copyOnClick, rootDir } = options;
|
|
25
|
-
publicConfig.vueGrab = {
|
|
26
|
-
...(publicConfig.vueGrab as Record<string, any> | undefined),
|
|
27
|
-
enabled,
|
|
28
|
-
overlayStyle,
|
|
29
|
-
copyOnClick,
|
|
30
|
-
rootDir: rootDir || nuxt.options.rootDir
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
nuxt.options.build.transpile = nuxt.options.build.transpile || [];
|
|
34
|
-
if (!nuxt.options.build.transpile.includes('vue-grab')) {
|
|
35
|
-
nuxt.options.build.transpile.push('vue-grab');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const resolver = createResolver(import.meta.url);
|
|
39
|
-
addPlugin({
|
|
40
|
-
src: resolver.resolve('./runtime/plugin'),
|
|
41
|
-
mode: 'client'
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
addVitePlugin({
|
|
45
|
-
name: 'vite-plugin-vue-grab-injector',
|
|
46
|
-
enforce: 'post',
|
|
47
|
-
transform(code, id) {
|
|
48
|
-
if (!id.match(/\.vue($|\?)/) || id.includes('node_modules')) return;
|
|
49
|
-
const [filename] = id.split('?');
|
|
50
|
-
if (!filename) return;
|
|
51
|
-
|
|
52
|
-
const file = filename.replace(nuxt.options.rootDir, '');
|
|
53
|
-
|
|
54
|
-
const getLineCol = (index: number) => {
|
|
55
|
-
const pre = code.slice(0, index);
|
|
56
|
-
const lines = pre.split('\n');
|
|
57
|
-
const line = lines.length;
|
|
58
|
-
const column = lines[lines.length - 1].length + 1;
|
|
59
|
-
return { line, column };
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// 1. Handle "export default _sfc_main" (common in script setup)
|
|
63
|
-
const matchVar = code.match(/export default\s+([a-zA-Z0-9_$]+)/);
|
|
64
|
-
if (matchVar && matchVar.index !== undefined) {
|
|
65
|
-
const name = matchVar[1];
|
|
66
|
-
// For variable export, the definition is usually earlier.
|
|
67
|
-
// We can't easily find the definition line without parsing.
|
|
68
|
-
// But we can fallback to 1, or try to find "const name ="?
|
|
69
|
-
// For script setup, the variable is defined near the top or bottom.
|
|
70
|
-
// Let's use 1 as fallback for variable export, or try to find definition.
|
|
71
|
-
// Actually, let's just stick to file path for now for variable, or use 1.
|
|
72
|
-
// Nuxt DevTools often uses 1 for SFCs unless it parses the template.
|
|
73
|
-
const inject = `\n${name}.__file = ${JSON.stringify(file)};\n${name}.__line = 1;\n${name}.__column = 1;\n`;
|
|
74
|
-
return {
|
|
75
|
-
code: code.replace(matchVar[0], inject + matchVar[0]),
|
|
76
|
-
map: null
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// 2. Handle "export default { ... }"
|
|
81
|
-
const matchObj = code.match(/export default\s*\{/);
|
|
82
|
-
if (matchObj && matchObj.index !== undefined) {
|
|
83
|
-
const { line, column } = getLineCol(matchObj.index);
|
|
84
|
-
return {
|
|
85
|
-
code: code.replace(/export default\s*\{/, `export default { __file: ${JSON.stringify(file)}, __line: ${line}, __column: ${column},`),
|
|
86
|
-
map: null
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// 3. Handle "export default defineComponent({ ... })"
|
|
91
|
-
const matchDef = code.match(/export default\s+defineComponent\s*\(\s*\{/);
|
|
92
|
-
if (matchDef && matchDef.index !== undefined) {
|
|
93
|
-
const { line, column } = getLineCol(matchDef.index);
|
|
94
|
-
return {
|
|
95
|
-
code: code.replace(/export default\s+defineComponent\s*\(\s*\{/, `export default defineComponent({ __file: ${JSON.stringify(file)}, __line: ${line}, __column: ${column},`),
|
|
96
|
-
map: null
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
});
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { defineNuxtPlugin, useRuntimeConfig } from '#app';
|
|
2
|
-
import { installVueGrab } from '../../core/api';
|
|
3
|
-
|
|
4
|
-
export default defineNuxtPlugin(() => {
|
|
5
|
-
const config = useRuntimeConfig().public?.vueGrab ?? {};
|
|
6
|
-
if (config.enabled === false) return;
|
|
7
|
-
if (typeof window === 'undefined') return;
|
|
8
|
-
installVueGrab(window, {
|
|
9
|
-
overlayStyle: config.overlayStyle,
|
|
10
|
-
copyOnClick: config.copyOnClick,
|
|
11
|
-
rootDir: config.rootDir
|
|
12
|
-
});
|
|
13
|
-
});
|
package/src/plugin.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { installVueGrab } from './core/api';
|
|
2
|
-
import type { VueGrabOptions } from './core/api';
|
|
3
|
-
|
|
4
|
-
export type VueGrabPluginOptions = VueGrabOptions & {
|
|
5
|
-
enabled?: boolean;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
function isDevEnvironment() {
|
|
9
|
-
if (typeof import.meta !== 'undefined' && (import.meta as any).env) {
|
|
10
|
-
return Boolean((import.meta as any).env.DEV);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
const globalScope =
|
|
15
|
-
typeof globalThis !== 'undefined' ? globalThis :
|
|
16
|
-
typeof window !== 'undefined' ? window :
|
|
17
|
-
typeof self !== 'undefined' ? self :
|
|
18
|
-
typeof global !== 'undefined' ? global : {};
|
|
19
|
-
|
|
20
|
-
const proc = (globalScope as any).process;
|
|
21
|
-
if (proc && proc.env) {
|
|
22
|
-
return proc.env.NODE_ENV !== 'production';
|
|
23
|
-
}
|
|
24
|
-
} catch {
|
|
25
|
-
// ignore
|
|
26
|
-
}
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function createVueGrabPlugin(options: VueGrabPluginOptions = {}) {
|
|
31
|
-
return {
|
|
32
|
-
install() {
|
|
33
|
-
const enabled =
|
|
34
|
-
typeof options.enabled === 'boolean' ? options.enabled : isDevEnvironment();
|
|
35
|
-
if (enabled && typeof window !== 'undefined') {
|
|
36
|
-
installVueGrab(window, {
|
|
37
|
-
overlayStyle: options.overlayStyle,
|
|
38
|
-
onCopy: options.onCopy,
|
|
39
|
-
copyOnClick: options.copyOnClick,
|
|
40
|
-
rootDir: options.rootDir,
|
|
41
|
-
domFileResolver: options.domFileResolver
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export default createVueGrabPlugin();
|
package/tsconfig.json
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// Visit https://aka.ms/tsconfig to read more about this file
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
// File Layout
|
|
5
|
-
// "rootDir": "./src",
|
|
6
|
-
// "outDir": "./dist",
|
|
7
|
-
|
|
8
|
-
// Environment Settings
|
|
9
|
-
// See also https://aka.ms/tsconfig/module
|
|
10
|
-
"module": "nodenext",
|
|
11
|
-
"target": "esnext",
|
|
12
|
-
"types": [],
|
|
13
|
-
// For nodejs:
|
|
14
|
-
// "lib": ["esnext"],
|
|
15
|
-
// "types": ["node"],
|
|
16
|
-
// and npm install -D @types/node
|
|
17
|
-
|
|
18
|
-
// Other Outputs
|
|
19
|
-
"sourceMap": true,
|
|
20
|
-
"declaration": true,
|
|
21
|
-
"declarationMap": true,
|
|
22
|
-
|
|
23
|
-
// Stricter Typechecking Options
|
|
24
|
-
"noUncheckedIndexedAccess": true,
|
|
25
|
-
"exactOptionalPropertyTypes": true,
|
|
26
|
-
|
|
27
|
-
// Style Options
|
|
28
|
-
// "noImplicitReturns": true,
|
|
29
|
-
// "noImplicitOverride": true,
|
|
30
|
-
// "noUnusedLocals": true,
|
|
31
|
-
// "noUnusedParameters": true,
|
|
32
|
-
// "noFallthroughCasesInSwitch": true,
|
|
33
|
-
// "noPropertyAccessFromIndexSignature": true,
|
|
34
|
-
|
|
35
|
-
// Recommended Options
|
|
36
|
-
"strict": true,
|
|
37
|
-
"jsx": "react-jsx",
|
|
38
|
-
"verbatimModuleSyntax": true,
|
|
39
|
-
"isolatedModules": true,
|
|
40
|
-
"noUncheckedSideEffectImports": true,
|
|
41
|
-
"moduleDetection": "force",
|
|
42
|
-
"skipLibCheck": true,
|
|
43
|
-
}
|
|
44
|
-
}
|