checkpoint-cli 0.4.0 → 0.5.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/index.js +12 -12
- package/dist/tracking-script-minimal.js +233 -79
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -446,12 +446,12 @@ function loginWithBrowser() {
|
|
|
446
446
|
const program = new commander_1.Command();
|
|
447
447
|
program
|
|
448
448
|
.name('checkpoint')
|
|
449
|
-
.description('Share your localhost with reviewers — get visual feedback directly on the page')
|
|
450
|
-
.version('0.
|
|
449
|
+
.description('Share your localhost with reviewers — get visual feedback directly on the page.\n\nQuick start:\n 1. checkpoint login Sign in to your Checkpoint account\n 2. checkpoint start -p 3000 Start tunneling and get a share link\n\nReuse a tunnel name to keep the same share URL and preserve all comments.')
|
|
450
|
+
.version('0.5.0');
|
|
451
451
|
// ── checkpoint login ──
|
|
452
452
|
program
|
|
453
453
|
.command('login')
|
|
454
|
-
.description('
|
|
454
|
+
.description('Sign in to your Checkpoint account. Opens the browser for authentication.')
|
|
455
455
|
.action(async () => {
|
|
456
456
|
console.log('');
|
|
457
457
|
console.log(chalk_1.default.blue.bold(' ⟐ Checkpoint'));
|
|
@@ -497,7 +497,7 @@ program
|
|
|
497
497
|
// ── checkpoint logout ──
|
|
498
498
|
program
|
|
499
499
|
.command('logout')
|
|
500
|
-
.description('Sign out and
|
|
500
|
+
.description('Sign out and clear saved credentials from this machine.')
|
|
501
501
|
.action(() => {
|
|
502
502
|
console.log('');
|
|
503
503
|
console.log(chalk_1.default.blue.bold(' ⟐ Checkpoint'));
|
|
@@ -509,9 +509,9 @@ program
|
|
|
509
509
|
// ── checkpoint start ──
|
|
510
510
|
program
|
|
511
511
|
.command('start')
|
|
512
|
-
.description('
|
|
513
|
-
.requiredOption('-p, --port <port>', 'Local port
|
|
514
|
-
.option('-n, --name <name>', '
|
|
512
|
+
.description('Start tunneling a local port and get a shareable link for reviewers.\nIf a tunnel with the same name already exists, it reconnects to it —\nkeeping the same share URL and all previous comments intact.')
|
|
513
|
+
.requiredOption('-p, --port <port>', 'Local port your dev server is running on (e.g. 3000, 5173)', '3000')
|
|
514
|
+
.option('-n, --name <name>', 'Tunnel name. Reuse a name to resume the same share URL.')
|
|
515
515
|
.option('--provider <provider>', 'Tunnel provider: cloudflared (default) or ngrok')
|
|
516
516
|
.action(async (opts) => {
|
|
517
517
|
requireAuth();
|
|
@@ -611,10 +611,10 @@ program
|
|
|
611
611
|
// ── checkpoint share ──
|
|
612
612
|
program
|
|
613
613
|
.command('share')
|
|
614
|
-
.description('Register an existing tunnel URL with Checkpoint')
|
|
615
|
-
.requiredOption('-u, --url <url>', '
|
|
614
|
+
.description('Register an existing tunnel URL (e.g. from ngrok) with Checkpoint.\nUse this if you already have a tunnel running and just need a share link.')
|
|
615
|
+
.requiredOption('-u, --url <url>', 'The public tunnel URL to register (https://...)')
|
|
616
616
|
.option('-n, --name <name>', 'Name for this tunnel', 'My Tunnel')
|
|
617
|
-
.option('-p, --port <port>', 'Local port
|
|
617
|
+
.option('-p, --port <port>', 'Local port for reference', '3000')
|
|
618
618
|
.action(async (opts) => {
|
|
619
619
|
requireAuth();
|
|
620
620
|
console.log('');
|
|
@@ -673,7 +673,7 @@ program
|
|
|
673
673
|
// ── checkpoint status ──
|
|
674
674
|
program
|
|
675
675
|
.command('status')
|
|
676
|
-
.description('
|
|
676
|
+
.description('Show login status and which tunnel providers are installed.')
|
|
677
677
|
.action(async () => {
|
|
678
678
|
console.log('');
|
|
679
679
|
console.log(chalk_1.default.blue.bold(' ⟐ Checkpoint — Status'));
|
|
@@ -711,7 +711,7 @@ program
|
|
|
711
711
|
// ── checkpoint whoami ──
|
|
712
712
|
program
|
|
713
713
|
.command('whoami')
|
|
714
|
-
.description('
|
|
714
|
+
.description('Print the email of the currently logged-in user.')
|
|
715
715
|
.action(async () => {
|
|
716
716
|
const config = (0, config_js_1.loadConfig)();
|
|
717
717
|
if (!config) {
|
|
@@ -14,7 +14,6 @@ function buildMinimalTrackingScript() {
|
|
|
14
14
|
var lastMouseX=0;
|
|
15
15
|
var lastMouseY=0;
|
|
16
16
|
var inspectBox=null;
|
|
17
|
-
var inspectLabel=null;
|
|
18
17
|
var pickShield=null;
|
|
19
18
|
var lastPath='';
|
|
20
19
|
var mutationTick=false;
|
|
@@ -147,6 +146,214 @@ function buildMinimalTrackingScript() {
|
|
|
147
146
|
return path.slice(-12);
|
|
148
147
|
}
|
|
149
148
|
|
|
149
|
+
function withFrameworkSuffix(path,framework){
|
|
150
|
+
var safePath=Array.isArray(path)?path.slice(0):[];
|
|
151
|
+
if(framework) safePath.push('@fw:'+framework);
|
|
152
|
+
return safePath.slice(-16);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function getVueComponentFromElement(el){
|
|
156
|
+
if(!el||el.nodeType!==1) return null;
|
|
157
|
+
var current=el;
|
|
158
|
+
var depth=0;
|
|
159
|
+
while(current&&depth<8){
|
|
160
|
+
try{
|
|
161
|
+
if(current.__vueParentComponent) return current.__vueParentComponent;
|
|
162
|
+
if(current.__vue__) return current.__vue__;
|
|
163
|
+
if(current.__vnode&¤t.__vnode.component) return current.__vnode.component;
|
|
164
|
+
}catch(e){}
|
|
165
|
+
current=current.parentElement;
|
|
166
|
+
depth++;
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function getVueComponentName(instance){
|
|
172
|
+
try{
|
|
173
|
+
if(!instance) return '';
|
|
174
|
+
if(instance.type){
|
|
175
|
+
var t=instance.type;
|
|
176
|
+
if(typeof t.name==='string'&&t.name) return t.name;
|
|
177
|
+
if(typeof t.__name==='string'&&t.__name) return t.__name;
|
|
178
|
+
if(typeof t.displayName==='string'&&t.displayName) return t.displayName;
|
|
179
|
+
}
|
|
180
|
+
if(instance.$options&&typeof instance.$options.name==='string'&&instance.$options.name){
|
|
181
|
+
return instance.$options.name;
|
|
182
|
+
}
|
|
183
|
+
}catch(e){}
|
|
184
|
+
return '';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function getVueSourceFile(instance){
|
|
188
|
+
try{
|
|
189
|
+
if(!instance) return '';
|
|
190
|
+
if(instance.type&&typeof instance.type.__file==='string'&&instance.type.__file) return instance.type.__file;
|
|
191
|
+
if(instance.$options&&typeof instance.$options.__file==='string'&&instance.$options.__file) return instance.$options.__file;
|
|
192
|
+
}catch(e){}
|
|
193
|
+
return '';
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function getVueOwnerPath(instance){
|
|
197
|
+
var path=[];
|
|
198
|
+
var current=instance;
|
|
199
|
+
var steps=0;
|
|
200
|
+
while(current&&steps<24){
|
|
201
|
+
var name=getVueComponentName(current);
|
|
202
|
+
var keyVal='';
|
|
203
|
+
try{
|
|
204
|
+
if(current.vnode&¤t.vnode.key!=null) keyVal=String(current.vnode.key);
|
|
205
|
+
else if(current.$vnode&¤t.$vnode.key!=null) keyVal=String(current.$vnode.key);
|
|
206
|
+
}catch(e){}
|
|
207
|
+
if(name) path.push(keyVal?name+'#'+keyVal:name);
|
|
208
|
+
current=current.parent||current.$parent||null;
|
|
209
|
+
steps++;
|
|
210
|
+
}
|
|
211
|
+
path.reverse();
|
|
212
|
+
return path.slice(-12);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function getVueInstanceKey(instance){
|
|
216
|
+
try{
|
|
217
|
+
if(!instance) return '';
|
|
218
|
+
if(instance.vnode&&instance.vnode.key!=null) return String(instance.vnode.key);
|
|
219
|
+
if(instance.$vnode&&instance.$vnode.key!=null) return String(instance.$vnode.key);
|
|
220
|
+
}catch(e){}
|
|
221
|
+
return '';
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function getSvelteMetaFromElement(el){
|
|
225
|
+
if(!el||el.nodeType!==1) return null;
|
|
226
|
+
var current=el;
|
|
227
|
+
var depth=0;
|
|
228
|
+
while(current&&depth<8){
|
|
229
|
+
try{
|
|
230
|
+
if(current.__svelte_meta) return current.__svelte_meta;
|
|
231
|
+
}catch(e){}
|
|
232
|
+
current=current.parentElement;
|
|
233
|
+
depth++;
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function basename(path){
|
|
239
|
+
if(!path) return '';
|
|
240
|
+
try{
|
|
241
|
+
var clean=String(path).split(/[\\/]/).pop()||'';
|
|
242
|
+
return clean;
|
|
243
|
+
}catch(e){}
|
|
244
|
+
return '';
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function withoutExt(name){
|
|
248
|
+
if(!name) return '';
|
|
249
|
+
return String(name).replace(/\.[^.]+$/,'');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function getAngularComponentFromElement(el){
|
|
253
|
+
var ngApi=null;
|
|
254
|
+
try{ ngApi=window.ng||null; }catch(e){ ngApi=null; }
|
|
255
|
+
if(!ngApi||typeof ngApi.getComponent!=='function') return null;
|
|
256
|
+
var current=el;
|
|
257
|
+
var depth=0;
|
|
258
|
+
while(current&&depth<8){
|
|
259
|
+
try{
|
|
260
|
+
var comp=ngApi.getComponent(current);
|
|
261
|
+
if(comp) return { component:comp, host:current };
|
|
262
|
+
}catch(e){}
|
|
263
|
+
current=current.parentElement;
|
|
264
|
+
depth++;
|
|
265
|
+
}
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function getAngularOwnerPath(el){
|
|
270
|
+
var ngApi=null;
|
|
271
|
+
try{ ngApi=window.ng||null; }catch(e){ ngApi=null; }
|
|
272
|
+
if(!ngApi||typeof ngApi.getComponent!=='function') return [];
|
|
273
|
+
var path=[];
|
|
274
|
+
var current=el;
|
|
275
|
+
var depth=0;
|
|
276
|
+
while(current&&depth<12){
|
|
277
|
+
try{
|
|
278
|
+
var comp=ngApi.getComponent(current);
|
|
279
|
+
if(comp&&comp.constructor&&comp.constructor.name){
|
|
280
|
+
path.push(String(comp.constructor.name));
|
|
281
|
+
}
|
|
282
|
+
}catch(e){}
|
|
283
|
+
current=current.parentElement;
|
|
284
|
+
depth++;
|
|
285
|
+
}
|
|
286
|
+
path.reverse();
|
|
287
|
+
return path.slice(-12);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function getFrameworkContextFromElement(el){
|
|
291
|
+
if(!el||el.nodeType!==1) return null;
|
|
292
|
+
|
|
293
|
+
var fiber=getReactFiberNode(el);
|
|
294
|
+
if(fiber){
|
|
295
|
+
var reactPath=getReactOwnerPathFromFiber(fiber);
|
|
296
|
+
var reactSource=getSourceDebugInfo(fiber);
|
|
297
|
+
return {
|
|
298
|
+
framework:'react',
|
|
299
|
+
component_name:getReactFiberName(fiber)||'',
|
|
300
|
+
owner_path:withFrameworkSuffix(reactPath,'react'),
|
|
301
|
+
source_file:reactSource&&reactSource.fileName?String(reactSource.fileName):'',
|
|
302
|
+
source_line:reactSource&&typeof reactSource.lineNumber==='number'?reactSource.lineNumber:undefined,
|
|
303
|
+
source_column:reactSource&&typeof reactSource.columnNumber==='number'?reactSource.columnNumber:undefined,
|
|
304
|
+
instance_key:fiber&&fiber.key!=null?String(fiber.key):''
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
var vueInstance=getVueComponentFromElement(el);
|
|
309
|
+
if(vueInstance){
|
|
310
|
+
var vueFile=getVueSourceFile(vueInstance);
|
|
311
|
+
return {
|
|
312
|
+
framework:'vue',
|
|
313
|
+
component_name:getVueComponentName(vueInstance)||withoutExt(basename(vueFile))||'',
|
|
314
|
+
owner_path:withFrameworkSuffix(getVueOwnerPath(vueInstance),'vue'),
|
|
315
|
+
source_file:vueFile||'',
|
|
316
|
+
source_line:undefined,
|
|
317
|
+
source_column:undefined,
|
|
318
|
+
instance_key:getVueInstanceKey(vueInstance)||''
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
var svelteMeta=getSvelteMetaFromElement(el);
|
|
323
|
+
if(svelteMeta){
|
|
324
|
+
var sLoc=svelteMeta.loc||null;
|
|
325
|
+
var sFile=sLoc&&sLoc.file?String(sLoc.file):'';
|
|
326
|
+
var sName=withoutExt(basename(sFile));
|
|
327
|
+
return {
|
|
328
|
+
framework:'svelte',
|
|
329
|
+
component_name:sName||'SvelteComponent',
|
|
330
|
+
owner_path:withFrameworkSuffix(sName?[sName]:[],'svelte'),
|
|
331
|
+
source_file:sFile||'',
|
|
332
|
+
source_line:sLoc&&typeof sLoc.line==='number'?sLoc.line:undefined,
|
|
333
|
+
source_column:sLoc&&typeof sLoc.column==='number'?sLoc.column:undefined,
|
|
334
|
+
instance_key:''
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
var ngMatch=getAngularComponentFromElement(el);
|
|
339
|
+
if(ngMatch&&ngMatch.component){
|
|
340
|
+
var ngName=(ngMatch.component.constructor&&ngMatch.component.constructor.name)
|
|
341
|
+
? String(ngMatch.component.constructor.name)
|
|
342
|
+
: 'AngularComponent';
|
|
343
|
+
return {
|
|
344
|
+
framework:'angular',
|
|
345
|
+
component_name:ngName,
|
|
346
|
+
owner_path:withFrameworkSuffix(getAngularOwnerPath(el),'angular'),
|
|
347
|
+
source_file:'',
|
|
348
|
+
source_line:undefined,
|
|
349
|
+
source_column:undefined,
|
|
350
|
+
instance_key:''
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
|
|
150
357
|
function getExplicitAnchorId(el){
|
|
151
358
|
if(!el||typeof el.closest!=='function') return '';
|
|
152
359
|
var holder=el.closest('[data-checkpoint-anchor]');
|
|
@@ -156,22 +363,26 @@ function buildMinimalTrackingScript() {
|
|
|
156
363
|
|
|
157
364
|
function getSourceAnchorFromElement(el){
|
|
158
365
|
if(!el||el.nodeType!==1) return null;
|
|
159
|
-
var fiber=getReactFiberNode(el);
|
|
160
|
-
var ownerPath=getReactOwnerPathFromFiber(fiber);
|
|
161
|
-
var source=getSourceDebugInfo(fiber);
|
|
162
|
-
var component=getReactFiberName(fiber);
|
|
163
366
|
var explicitId=getExplicitAnchorId(el);
|
|
164
|
-
var
|
|
165
|
-
var hasData=!!(
|
|
367
|
+
var context=getFrameworkContextFromElement(el);
|
|
368
|
+
var hasData=!!(
|
|
369
|
+
explicitId||
|
|
370
|
+
(context&&(
|
|
371
|
+
context.component_name||
|
|
372
|
+
(Array.isArray(context.owner_path)&&context.owner_path.length>0)||
|
|
373
|
+
context.source_file||
|
|
374
|
+
context.instance_key
|
|
375
|
+
))
|
|
376
|
+
);
|
|
166
377
|
if(!hasData) return null;
|
|
167
378
|
return {
|
|
168
379
|
explicit_id:explicitId||undefined,
|
|
169
|
-
component_name:
|
|
170
|
-
owner_path:
|
|
171
|
-
source_file:
|
|
172
|
-
source_line:
|
|
173
|
-
source_column:
|
|
174
|
-
react_key:
|
|
380
|
+
component_name:context&&context.component_name?context.component_name:undefined,
|
|
381
|
+
owner_path:context&&Array.isArray(context.owner_path)?context.owner_path:[],
|
|
382
|
+
source_file:context&&context.source_file?context.source_file:undefined,
|
|
383
|
+
source_line:context&&typeof context.source_line==='number'?context.source_line:undefined,
|
|
384
|
+
source_column:context&&typeof context.source_column==='number'?context.source_column:undefined,
|
|
385
|
+
react_key:context&&context.instance_key?context.instance_key:undefined,
|
|
175
386
|
host_tag:el&&el.tagName?String(el.tagName).toLowerCase():undefined
|
|
176
387
|
};
|
|
177
388
|
}
|
|
@@ -249,17 +460,16 @@ function buildMinimalTrackingScript() {
|
|
|
249
460
|
if(explicit===sourceAnchor.explicit_id) score+=2400;
|
|
250
461
|
else if(explicit) score-=200;
|
|
251
462
|
}
|
|
252
|
-
var
|
|
253
|
-
var component=
|
|
254
|
-
var
|
|
255
|
-
var ownerPath=getReactOwnerPathFromFiber(fiber);
|
|
463
|
+
var context=getFrameworkContextFromElement(el);
|
|
464
|
+
var component=context&&context.component_name?context.component_name:'';
|
|
465
|
+
var ownerPath=context&&Array.isArray(context.owner_path)?context.owner_path:[];
|
|
256
466
|
if(sourceAnchor.component_name&&component===sourceAnchor.component_name) score+=240;
|
|
257
|
-
if(sourceAnchor.react_key&&
|
|
467
|
+
if(sourceAnchor.react_key&&context&&context.instance_key&&String(context.instance_key)===sourceAnchor.react_key) score+=360;
|
|
258
468
|
score+=ownerSuffixScore(ownerPath,sourceAnchor.owner_path||[]);
|
|
259
|
-
if(sourceAnchor.source_file&&
|
|
469
|
+
if(sourceAnchor.source_file&&context&&context.source_file&&String(context.source_file||'')===String(sourceAnchor.source_file)){
|
|
260
470
|
score+=420;
|
|
261
|
-
if(typeof sourceAnchor.source_line==='number'&&
|
|
262
|
-
if(typeof sourceAnchor.source_column==='number'&&
|
|
471
|
+
if(typeof sourceAnchor.source_line==='number'&&context.source_line===sourceAnchor.source_line) score+=420;
|
|
472
|
+
if(typeof sourceAnchor.source_column==='number'&&context.source_column===sourceAnchor.source_column) score+=80;
|
|
263
473
|
}
|
|
264
474
|
if(sourceAnchor.host_tag&&el.tagName&&String(el.tagName).toLowerCase()===sourceAnchor.host_tag) score+=40;
|
|
265
475
|
return score;
|
|
@@ -451,29 +661,6 @@ function buildMinimalTrackingScript() {
|
|
|
451
661
|
return { coordFallback:null, strategy:'none', matchedSelector:null, status:'none' };
|
|
452
662
|
}
|
|
453
663
|
|
|
454
|
-
function getInspectLabelText(target){
|
|
455
|
-
if(!target||!target.tagName) return '';
|
|
456
|
-
var tag=String(target.tagName).toLowerCase();
|
|
457
|
-
var id=target.id?('#'+target.id):'';
|
|
458
|
-
var cls='';
|
|
459
|
-
try{
|
|
460
|
-
var classes=(target.className&&typeof target.className==='string')
|
|
461
|
-
? target.className.trim().split(/\s+/).filter(Boolean).slice(0,3)
|
|
462
|
-
: [];
|
|
463
|
-
if(classes.length>0) cls='.'+classes.join('.');
|
|
464
|
-
}catch(e){}
|
|
465
|
-
var selector=shortText(tag+id+cls);
|
|
466
|
-
var anchor=findBestAnchorableElement(target).sourceAnchor;
|
|
467
|
-
var source='(no source)';
|
|
468
|
-
if(anchor){
|
|
469
|
-
var file=anchor.source_file?String(anchor.source_file).split(/[\\/]/).pop():'';
|
|
470
|
-
if(file&&typeof anchor.source_line==='number') source=file+':'+anchor.source_line;
|
|
471
|
-
else if(file) source=file;
|
|
472
|
-
else if(anchor.component_name) source=anchor.component_name;
|
|
473
|
-
if(anchor.explicit_id) source=source+' · #'+anchor.explicit_id;
|
|
474
|
-
}
|
|
475
|
-
return selector+'\n'+source;
|
|
476
|
-
}
|
|
477
664
|
|
|
478
665
|
function ensureInspectUi(){
|
|
479
666
|
if(!document.body) return;
|
|
@@ -493,31 +680,10 @@ inspectBox.style.border='2px solid #F26522';
|
|
|
493
680
|
inspectBox.style.display='none';
|
|
494
681
|
document.body.appendChild(inspectBox);
|
|
495
682
|
}
|
|
496
|
-
if(!inspectLabel){
|
|
497
|
-
inspectLabel=document.createElement('div');
|
|
498
|
-
inspectLabel.style.position='fixed';
|
|
499
|
-
inspectLabel.style.left='0';
|
|
500
|
-
inspectLabel.style.top='0';
|
|
501
|
-
inspectLabel.style.padding='6px 8px';
|
|
502
|
-
inspectLabel.style.maxWidth='420px';
|
|
503
|
-
inspectLabel.style.borderRadius='8px';
|
|
504
|
-
inspectLabel.style.border='1px solid rgba(148,163,184,0.45)';
|
|
505
|
-
inspectLabel.style.background='rgba(15,23,42,0.96)';
|
|
506
|
-
inspectLabel.style.color='#e2e8f0';
|
|
507
|
-
inspectLabel.style.font='12px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace';
|
|
508
|
-
inspectLabel.style.whiteSpace='pre-line';
|
|
509
|
-
inspectLabel.style.wordBreak='break-word';
|
|
510
|
-
inspectLabel.style.pointerEvents='none';
|
|
511
|
-
inspectLabel.style.zIndex='2147483647';
|
|
512
|
-
inspectLabel.style.display='none';
|
|
513
|
-
inspectLabel.style.boxShadow='0 6px 20px rgba(0,0,0,0.35)';
|
|
514
|
-
document.body.appendChild(inspectLabel);
|
|
515
|
-
}
|
|
516
683
|
}
|
|
517
684
|
|
|
518
685
|
function hideInspectUi(){
|
|
519
|
-
|
|
520
|
-
if(inspectLabel) inspectLabel.style.display='none';
|
|
686
|
+
if(inspectBox) inspectBox.style.display='none';
|
|
521
687
|
}
|
|
522
688
|
|
|
523
689
|
function ensurePickShield(){
|
|
@@ -544,7 +710,7 @@ inspectBox.style.border='2px solid #F26522';
|
|
|
544
710
|
|
|
545
711
|
function renderInspectAt(x,y){
|
|
546
712
|
ensureInspectUi();
|
|
547
|
-
|
|
713
|
+
if(!inspectBox){
|
|
548
714
|
return;
|
|
549
715
|
}
|
|
550
716
|
var target=getElementAtPoint(x,y);
|
|
@@ -562,18 +728,6 @@ inspectBox.style.border='2px solid #F26522';
|
|
|
562
728
|
inspectBox.style.top=Math.max(0,rect.top)+'px';
|
|
563
729
|
inspectBox.style.width=Math.max(1,rect.width)+'px';
|
|
564
730
|
inspectBox.style.height=Math.max(1,rect.height)+'px';
|
|
565
|
-
inspectLabel.textContent=getInspectLabelText(target);
|
|
566
|
-
inspectLabel.style.display='block';
|
|
567
|
-
|
|
568
|
-
var vw=window.innerWidth||document.documentElement.clientWidth||0;
|
|
569
|
-
var vh=window.innerHeight||document.documentElement.clientHeight||0;
|
|
570
|
-
var lr=inspectLabel.getBoundingClientRect();
|
|
571
|
-
var left=x+12;
|
|
572
|
-
var top=y+12;
|
|
573
|
-
if(left+lr.width>vw-8) left=Math.max(8,x-lr.width-12);
|
|
574
|
-
if(top+lr.height>vh-8) top=Math.max(8,y-lr.height-12);
|
|
575
|
-
inspectLabel.style.left=left+'px';
|
|
576
|
-
inspectLabel.style.top=top+'px';
|
|
577
731
|
}
|
|
578
732
|
|
|
579
733
|
function postPickResult(target,clientX,clientY){
|