checkpoint-cli 1.0.2 → 1.0.3

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
@@ -106,10 +106,33 @@ async function getAuthenticatedClient() {
106
106
  }
107
107
  /* ── Injection Proxy ── */
108
108
  function startInjectionProxy(targetPort) {
109
- const scriptBody = (0, tracking_script_minimal_js_1.buildMinimalTrackingScript)().replace(/<\/script/gi, '<\\/script');
110
- const SCRIPT = `<script data-checkpoint-script="minimal-v1">\n${scriptBody}\n</script>`;
109
+ const AGENT_PATH = '/__checkpoint/agent.min.js';
110
+ const agentScript = (0, tracking_script_minimal_js_1.buildMinimalTrackingScript)();
111
+ const extractNonce = (html) => {
112
+ const nonceMatch = html.match(/<script\b[^>]*\bnonce=(?:"([^"]+)"|'([^']+)'|([^\s>]+))/i);
113
+ return nonceMatch?.[1] ?? nonceMatch?.[2] ?? nonceMatch?.[3] ?? null;
114
+ };
115
+ const buildInjectionTag = (html) => {
116
+ const nonce = extractNonce(html);
117
+ const nonceAttr = nonce ? ` nonce="${nonce.replace(/"/g, '&quot;')}"` : '';
118
+ return `<script data-checkpoint-script="minimal-v1" src="${AGENT_PATH}"${nonceAttr} defer></script>`;
119
+ };
111
120
  return new Promise((resolve, reject) => {
112
121
  const server = http_1.default.createServer((req, res) => {
122
+ const pathname = new URL(req.url || '/', 'http://checkpoint.local').pathname;
123
+ if (pathname === AGENT_PATH) {
124
+ res.writeHead(200, {
125
+ 'content-type': 'application/javascript; charset=utf-8',
126
+ 'cache-control': 'no-store, max-age=0',
127
+ 'x-content-type-options': 'nosniff',
128
+ });
129
+ if (req.method === 'HEAD') {
130
+ res.end();
131
+ return;
132
+ }
133
+ res.end(agentScript);
134
+ return;
135
+ }
113
136
  const fwdHeaders = { ...req.headers, host: `localhost:${targetPort}` };
114
137
  delete fwdHeaders['accept-encoding'];
115
138
  const proxyReq = http_1.default.request({
@@ -130,15 +153,16 @@ function startInjectionProxy(targetPort) {
130
153
  proxyRes.on('data', (chunk) => chunks.push(chunk));
131
154
  proxyRes.on('end', () => {
132
155
  let body = Buffer.concat(chunks).toString('utf-8');
156
+ const scriptTag = buildInjectionTag(body);
133
157
  if (!body.includes('data-checkpoint-script="minimal-v1"')) {
134
158
  if (body.includes('</head>')) {
135
- body = body.replace('</head>', () => SCRIPT + '\n</head>');
159
+ body = body.replace('</head>', () => scriptTag + '\n</head>');
136
160
  }
137
161
  else if (body.includes('</body>')) {
138
- body = body.replace('</body>', () => SCRIPT + '\n</body>');
162
+ body = body.replace('</body>', () => scriptTag + '\n</body>');
139
163
  }
140
164
  else {
141
- body += SCRIPT;
165
+ body += scriptTag;
142
166
  }
143
167
  }
144
168
  const headers = { ...proxyRes.headers };
@@ -18,6 +18,23 @@ function buildMinimalTrackingScript() {
18
18
  var lastPath='';
19
19
  var mutationTick=false;
20
20
  var pendingPickCommit=false;
21
+ var parentTargetOrigin='*';
22
+
23
+ function initParentOrigin(){
24
+ try{
25
+ if(!document.referrer) return;
26
+ var parsed=new URL(document.referrer);
27
+ if(parsed.protocol==='http:'||parsed.protocol==='https:') parentTargetOrigin=parsed.origin;
28
+ }catch(e){}
29
+ }
30
+
31
+ function postToParent(payload){
32
+ try{
33
+ window.parent.postMessage(payload,parentTargetOrigin);
34
+ return;
35
+ }catch(e){}
36
+ try{ window.parent.postMessage(payload,'*'); }catch(e){}
37
+ }
21
38
 
22
39
  function getMetrics(){
23
40
  var de=document.documentElement;
@@ -31,6 +48,27 @@ function buildMinimalTrackingScript() {
31
48
  };
32
49
  }
33
50
 
51
+ function reportReady(){
52
+ try{
53
+ postToParent({
54
+ type:'checkpoint:ready',
55
+ path:location.pathname+location.search+location.hash,
56
+ version:'minimal-v1',
57
+ capabilities:{ pickMode:true, resolveAnchors:true, sourceAnchors:true }
58
+ });
59
+ }catch(e){}
60
+ }
61
+
62
+ function reportDiagnostic(code,detail){
63
+ try{
64
+ postToParent({
65
+ type:'checkpoint:diagnostic',
66
+ code:code||'unknown',
67
+ detail:detail||''
68
+ });
69
+ }catch(e){}
70
+ }
71
+
34
72
  function clampPercent(v){
35
73
  if(v<0) return 0;
36
74
  if(v>100) return 100;
@@ -732,7 +770,7 @@ inspectBox.style.border='2px solid #F26522';
732
770
 
733
771
  function postPickResult(target,clientX,clientY){
734
772
  var payload=buildAnchorPayload(target,clientX,clientY);
735
- window.parent.postMessage({
773
+ postToParent({
736
774
  type:'checkpoint:pickResult',
737
775
  path:location.pathname+location.search+location.hash,
738
776
  anchorPayload:payload,
@@ -742,7 +780,7 @@ inspectBox.style.border='2px solid #F26522';
742
780
  scrollY:payload.coord_fallback&&typeof payload.coord_fallback.scroll_y==='number'?payload.coord_fallback.scroll_y:0,
743
781
  viewHeight:payload.coord_fallback&&typeof payload.coord_fallback.viewport_height==='number'?payload.coord_fallback.viewport_height:0
744
782
  }
745
- },'*');
783
+ });
746
784
  }
747
785
 
748
786
  function setPickMode(enabled){
@@ -854,7 +892,7 @@ inspectBox.style.border='2px solid #F26522';
854
892
  function reportScroll(){
855
893
  try{
856
894
  var m=getMetrics();
857
- window.parent.postMessage({
895
+ postToParent({
858
896
  type:'checkpoint:scroll',
859
897
  scrollX:m.scrollX,
860
898
  scrollY:m.scrollY,
@@ -862,7 +900,7 @@ inspectBox.style.border='2px solid #F26522';
862
900
  docHeight:m.docHeight,
863
901
  viewWidth:m.viewWidth,
864
902
  viewHeight:m.viewHeight
865
- },'*');
903
+ });
866
904
  }catch(e){}
867
905
  }
868
906
 
@@ -871,7 +909,7 @@ inspectBox.style.border='2px solid #F26522';
871
909
  var p=location.pathname+location.search+location.hash;
872
910
  if(p===lastPath) return;
873
911
  lastPath=p;
874
- window.parent.postMessage({ type:'checkpoint:navigate', path:p },'*');
912
+ postToParent({ type:'checkpoint:navigate', path:p });
875
913
  reportScroll();
876
914
  }catch(e){}
877
915
  }
@@ -881,11 +919,11 @@ inspectBox.style.border='2px solid #F26522';
881
919
  mutationTick=true;
882
920
  requestAnimationFrame(function(){
883
921
  mutationTick=false;
884
- window.parent.postMessage({
922
+ postToParent({
885
923
  type:'checkpoint:domMutation',
886
924
  reason:'mutation',
887
925
  path:location.pathname+location.search+location.hash
888
- },'*');
926
+ });
889
927
  });
890
928
  }
891
929
 
@@ -895,9 +933,13 @@ inspectBox.style.border='2px solid #F26522';
895
933
  var observer=new MutationObserver(function(){ reportDomMutation(); });
896
934
  observer.observe(document.documentElement,{ childList:true, subtree:true, attributes:true });
897
935
  window.addEventListener('beforeunload',function(){ try{observer.disconnect();}catch(e){}; });
898
- }catch(e){}
936
+ }catch(e){
937
+ reportDiagnostic('mutation_observer_failed',String(e&&e.message?e.message:e));
938
+ }
899
939
  }
900
940
 
941
+ initParentOrigin();
942
+ reportReady();
901
943
  reportNav();
902
944
  reportScroll();
903
945
  setupMutationObserver();
@@ -912,6 +954,7 @@ inspectBox.style.border='2px solid #F26522';
912
954
 
913
955
  window.addEventListener('message',function(e){
914
956
  try{
957
+ if(e.source!==window.parent) return;
915
958
  var d=e.data;
916
959
  if(!d||typeof d!=='object') return;
917
960
  if(d.type==='checkpoint:scrollTo'&&typeof d.y==='number'){
@@ -937,11 +980,11 @@ inspectBox.style.border='2px solid #F26522';
937
980
  coordFallback:result.coordFallback||null
938
981
  });
939
982
  }
940
- window.parent.postMessage({
983
+ postToParent({
941
984
  type:'checkpoint:anchorsResolved',
942
985
  path:location.pathname+location.search+location.hash,
943
986
  positions:positions
944
- },'*');
987
+ });
945
988
  }
946
989
  }catch(ex){}
947
990
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "checkpoint-cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Share your localhost with reviewers — get visual feedback directly on the page",
5
5
  "keywords": [
6
6
  "checkpoint",