checkpoint-cli 0.3.6 → 0.3.8

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 CHANGED
@@ -1606,7 +1606,7 @@ const program = new commander_1.Command();
1606
1606
  program
1607
1607
  .name('checkpoint')
1608
1608
  .description('Share your localhost with reviewers — get visual feedback directly on the page')
1609
- .version('0.3.6');
1609
+ .version('0.3.8');
1610
1610
  // ── checkpoint login ──
1611
1611
  program
1612
1612
  .command('login')
@@ -43,6 +43,49 @@ function buildMinimalTrackingScript() {
43
43
  return String(value).replace(/\s+/g,' ').trim().slice(0,120);
44
44
  }
45
45
 
46
+ function normalizedText(value){
47
+ return shortText(value).toLowerCase();
48
+ }
49
+
50
+ function getNodeText(node){
51
+ try{
52
+ if(!node||!node.textContent) return '';
53
+ return normalizedText(node.textContent);
54
+ }catch(e){}
55
+ return '';
56
+ }
57
+
58
+ function getTextContext(target){
59
+ if(!target||target.nodeType!==1) return null;
60
+ var self=getNodeText(target);
61
+ var parent=getNodeText(target.parentElement);
62
+ var before=getNodeText(target.previousElementSibling);
63
+ var after=getNodeText(target.nextElementSibling);
64
+
65
+ // If clicked node has no text (e.g. image/icon), borrow nearest parent text.
66
+ if(!self){
67
+ var current=target.parentElement;
68
+ var depth=0;
69
+ while(current&&depth<4&&!self){
70
+ var candidate=getNodeText(current);
71
+ if(candidate&&candidate.length>=3){
72
+ self=candidate;
73
+ break;
74
+ }
75
+ current=current.parentElement;
76
+ depth++;
77
+ }
78
+ }
79
+
80
+ if(!self&&!parent&&!before&&!after) return null;
81
+ return {
82
+ self:self||undefined,
83
+ parent:parent||undefined,
84
+ before:before||undefined,
85
+ after:after||undefined
86
+ };
87
+ }
88
+
46
89
  function cssEscape(value){
47
90
  try{
48
91
  if(window.CSS&&typeof window.CSS.escape==='function') return window.CSS.escape(value);
@@ -147,6 +190,15 @@ function buildMinimalTrackingScript() {
147
190
  return score;
148
191
  }
149
192
 
193
+ function hasOwnerPathKey(anchor){
194
+ if(!anchor||!Array.isArray(anchor.owner_path)) return false;
195
+ for(var i=0;i<anchor.owner_path.length;i++){
196
+ var part=anchor.owner_path[i];
197
+ if(typeof part==='string'&&part.indexOf('#')>0) return true;
198
+ }
199
+ return false;
200
+ }
201
+
150
202
  function findBestAnchorableElement(el){
151
203
  if(!el||el.nodeType!==1) return { element:el, sourceAnchor:null };
152
204
  var current=el;
@@ -165,6 +217,10 @@ function buildMinimalTrackingScript() {
165
217
  if(anchor&&anchor.explicit_id){
166
218
  return { element:current, sourceAnchor:anchor };
167
219
  }
220
+ // Prefer keyed instances in repeated lists/grids.
221
+ if(anchor&&(anchor.react_key||hasOwnerPathKey(anchor))){
222
+ return { element:current, sourceAnchor:anchor };
223
+ }
168
224
  current=current.parentElement;
169
225
  depth++;
170
226
  }
@@ -178,7 +234,7 @@ function buildMinimalTrackingScript() {
178
234
  var score=0;
179
235
  while(i>=0&&j>=0){
180
236
  if(current[i]!==expected[j]) break;
181
- score+=100;
237
+ score+=(String(expected[j]).indexOf('#')>0?180:100);
182
238
  i--;
183
239
  j--;
184
240
  }
@@ -290,10 +346,11 @@ function buildMinimalTrackingScript() {
290
346
  var metrics=getMetrics();
291
347
  var sourceTarget=findBestAnchorableElement(el);
292
348
  var anchorEl=sourceTarget.element||el;
349
+ var textContext=getTextContext(el)||getTextContext(anchorEl);
293
350
  return {
294
351
  selector_chain:[],
295
352
  dom_fingerprint:null,
296
- text_context:null,
353
+ text_context:textContext,
297
354
  container_hint:null,
298
355
  transient_context:null,
299
356
  source_anchor:sourceTarget.sourceAnchor||getSourceAnchorFromElement(anchorEl),
@@ -301,6 +358,31 @@ function buildMinimalTrackingScript() {
301
358
  };
302
359
  }
303
360
 
361
+ function textMatchBonus(node,textContext){
362
+ if(!textContext||typeof textContext!=='object') return 0;
363
+ var score=0;
364
+ var self=getNodeText(node);
365
+ var parent=getNodeText(node&&node.parentElement);
366
+ if(textContext.self&&self){
367
+ if(self===textContext.self) score+=280;
368
+ else if(self.indexOf(textContext.self)>=0||textContext.self.indexOf(self)>=0) score+=130;
369
+ else score-=40;
370
+ }
371
+ if(textContext.parent&&parent){
372
+ if(parent===textContext.parent) score+=180;
373
+ else if(parent.indexOf(textContext.parent)>=0||textContext.parent.indexOf(parent)>=0) score+=90;
374
+ }
375
+ if(textContext.before){
376
+ var prev=getNodeText(node&&node.previousElementSibling);
377
+ if(prev&&prev===textContext.before) score+=55;
378
+ }
379
+ if(textContext.after){
380
+ var next=getNodeText(node&&node.nextElementSibling);
381
+ if(next&&next===textContext.after) score+=55;
382
+ }
383
+ return score;
384
+ }
385
+
304
386
  function findBySource(sourceAnchor,payload,scope){
305
387
  if(!sourceAnchor||typeof sourceAnchor!=='object') return null;
306
388
  var searchScope=scope||document;
@@ -322,6 +404,7 @@ function buildMinimalTrackingScript() {
322
404
  var node=nodes[i];
323
405
  var score=sourceMatchScore(node,sourceAnchor);
324
406
  if(score<=0) continue;
407
+ score+=textMatchBonus(node,payload&&payload.text_context);
325
408
  if(targetDocPoint&&node.getBoundingClientRect){
326
409
  var r=node.getBoundingClientRect();
327
410
  var centerX=r.left+(r.width/2)+metrics.scrollX;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "checkpoint-cli",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Share your localhost with reviewers — get visual feedback directly on the page",
5
5
  "keywords": [
6
6
  "checkpoint",