web-remarq 0.1.2 → 0.1.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.
@@ -187,8 +187,17 @@ var WebRemarq = (() => {
187
187
  return id;
188
188
  }
189
189
  function getTextContent(el) {
190
- var _a, _b;
191
- const text = (_b = (_a = el.textContent) == null ? void 0 : _a.trim()) != null ? _b : null;
190
+ var _a, _b, _c;
191
+ let text = "";
192
+ for (const node of Array.from(el.childNodes)) {
193
+ if (node.nodeType === Node.TEXT_NODE) {
194
+ text += (_a = node.textContent) != null ? _a : "";
195
+ }
196
+ }
197
+ text = text.trim();
198
+ if (!text && el.children.length <= 3) {
199
+ text = (_c = (_b = el.textContent) == null ? void 0 : _b.trim()) != null ? _c : "";
200
+ }
192
201
  if (!text) return null;
193
202
  return text.length > TEXT_MAX_LENGTH ? text.slice(0, TEXT_MAX_LENGTH) : text;
194
203
  }
@@ -477,7 +486,7 @@ var WebRemarq = (() => {
477
486
  .remarq-marker[data-status="resolved"] { background: var(--remarq-resolved); opacity: 0.7; }
478
487
 
479
488
  .remarq-popup {
480
- position: fixed;
489
+ position: absolute;
481
490
  z-index: 2147483647;
482
491
  width: 300px;
483
492
  background: var(--remarq-bg);
@@ -780,13 +789,13 @@ var WebRemarq = (() => {
780
789
  this.exportMenu = document.createElement("div");
781
790
  this.exportMenu.className = "remarq-export-menu";
782
791
  const mdBtn = document.createElement("button");
783
- mdBtn.textContent = "Markdown (clipboard)";
792
+ mdBtn.textContent = "Markdown (file)";
784
793
  mdBtn.addEventListener("click", () => {
785
794
  this.callbacks.onExportMd();
786
795
  this.closeExportMenu();
787
796
  });
788
797
  const jsonBtn = document.createElement("button");
789
- jsonBtn.textContent = "JSON (file)";
798
+ jsonBtn.textContent = "JSON (clipboard)";
790
799
  jsonBtn.addEventListener("click", () => {
791
800
  this.callbacks.onExportJson();
792
801
  this.closeExportMenu();
@@ -819,7 +828,6 @@ var WebRemarq = (() => {
819
828
  container.appendChild(this.tooltipEl);
820
829
  }
821
830
  show(target) {
822
- var _a;
823
831
  try {
824
832
  const rect = target.getBoundingClientRect();
825
833
  this.overlayEl.style.display = "block";
@@ -827,13 +835,7 @@ var WebRemarq = (() => {
827
835
  this.overlayEl.style.left = `${rect.left}px`;
828
836
  this.overlayEl.style.width = `${rect.width}px`;
829
837
  this.overlayEl.style.height = `${rect.height}px`;
830
- const tag = target.tagName.toLowerCase();
831
- const text = ((_a = target.textContent) == null ? void 0 : _a.trim().slice(0, 30)) || "";
832
- const dataAnnotate = target.getAttribute("data-annotate");
833
- let label = `<${tag}>`;
834
- if (text) label += ` "${text}"`;
835
- if (dataAnnotate) label += ` [${dataAnnotate}]`;
836
- this.tooltipEl.textContent = label;
838
+ this.tooltipEl.textContent = describeElement(target);
837
839
  this.tooltipEl.style.display = "block";
838
840
  this.tooltipEl.style.top = `${rect.top - 28}px`;
839
841
  this.tooltipEl.style.left = `${rect.left}px`;
@@ -854,6 +856,43 @@ var WebRemarq = (() => {
854
856
  this.tooltipEl.remove();
855
857
  }
856
858
  };
859
+ function describeElement(el) {
860
+ const tag = el.tagName.toLowerCase();
861
+ const parts = [`<${tag}>`];
862
+ const dataAnnotate = el.getAttribute("data-annotate");
863
+ const dataTestId = el.getAttribute("data-testid") || el.getAttribute("data-test") || el.getAttribute("data-cy");
864
+ if (dataAnnotate) {
865
+ parts.push(`[${dataAnnotate}]`);
866
+ } else if (dataTestId) {
867
+ parts.push(`[${dataTestId}]`);
868
+ }
869
+ if (el.id) {
870
+ parts.push(`#${el.id}`);
871
+ }
872
+ const classes = Array.from(el.classList).filter((c) => !c.match(/^(sc-|css-)/) && !c.match(/^[a-zA-Z0-9]{8,}$/) && !c.match(/__[a-zA-Z0-9]{3,}$/)).slice(0, 2);
873
+ if (classes.length) {
874
+ parts.push(`.${classes.join(".")}`);
875
+ }
876
+ const directText = getDirectText(el);
877
+ if (directText) {
878
+ parts.push(`"${directText}"`);
879
+ }
880
+ return parts.join(" ");
881
+ }
882
+ function getDirectText(el) {
883
+ var _a, _b, _c;
884
+ let text = "";
885
+ for (const node of Array.from(el.childNodes)) {
886
+ if (node.nodeType === Node.TEXT_NODE) {
887
+ text += (_a = node.textContent) != null ? _a : "";
888
+ }
889
+ }
890
+ text = text.trim();
891
+ if (!text && el.children.length <= 2) {
892
+ text = (_c = (_b = el.textContent) == null ? void 0 : _b.trim()) != null ? _c : "";
893
+ }
894
+ return text.slice(0, 30);
895
+ }
857
896
 
858
897
  // src/ui/popup.ts
859
898
  var POPUP_WIDTH = 300;
@@ -900,7 +939,10 @@ var WebRemarq = (() => {
900
939
  popup2.appendChild(actions);
901
940
  this.container.appendChild(popup2);
902
941
  this.popupEl = popup2;
903
- this.adjustPosition(popup2, position);
942
+ requestAnimationFrame(() => {
943
+ this.adjustPosition(popup2, position);
944
+ textarea.focus();
945
+ });
904
946
  this.keyHandler = (e) => {
905
947
  if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
906
948
  const comment = textarea.value.trim();
@@ -914,7 +956,6 @@ var WebRemarq = (() => {
914
956
  }
915
957
  };
916
958
  document.addEventListener("keydown", this.keyHandler);
917
- requestAnimationFrame(() => textarea.focus());
918
959
  }
919
960
  showDetail(info, position, callbacks) {
920
961
  this.hide();
@@ -957,7 +998,9 @@ var WebRemarq = (() => {
957
998
  popup2.appendChild(actions);
958
999
  this.container.appendChild(popup2);
959
1000
  this.popupEl = popup2;
960
- this.adjustPosition(popup2, position);
1001
+ requestAnimationFrame(() => {
1002
+ this.adjustPosition(popup2, position);
1003
+ });
961
1004
  this.keyHandler = (e) => {
962
1005
  if (e.key === "Escape") {
963
1006
  this.hide();
@@ -980,22 +1023,22 @@ var WebRemarq = (() => {
980
1023
  this.hide();
981
1024
  }
982
1025
  adjustPosition(popup2, position) {
983
- const popupRect = popup2.getBoundingClientRect();
984
- const viewH = window.innerHeight;
985
- const viewW = window.innerWidth;
1026
+ const popupHeight = popup2.offsetHeight;
1027
+ const viewportBottom = window.scrollY + window.innerHeight;
1028
+ const viewportRight = window.scrollX + window.innerWidth;
986
1029
  let top = position.top;
987
1030
  let left = position.left;
988
- if (top + popupRect.height > viewH - POPUP_MARGIN) {
989
- top = position.top - popupRect.height - 16;
1031
+ if (top + popupHeight > viewportBottom - POPUP_MARGIN) {
1032
+ top = position.anchorBottom - popupHeight;
990
1033
  }
991
- if (top < POPUP_MARGIN) {
992
- top = POPUP_MARGIN;
1034
+ if (top < window.scrollY + POPUP_MARGIN) {
1035
+ top = window.scrollY + POPUP_MARGIN;
993
1036
  }
994
- if (left + POPUP_WIDTH > viewW - POPUP_MARGIN) {
995
- left = viewW - POPUP_WIDTH - POPUP_MARGIN;
1037
+ if (left + POPUP_WIDTH > viewportRight - POPUP_MARGIN) {
1038
+ left = viewportRight - POPUP_WIDTH - POPUP_MARGIN;
996
1039
  }
997
- if (left < POPUP_MARGIN) {
998
- left = POPUP_MARGIN;
1040
+ if (left < window.scrollX + POPUP_MARGIN) {
1041
+ left = window.scrollX + POPUP_MARGIN;
999
1042
  }
1000
1043
  popup2.style.top = `${top}px`;
1001
1044
  popup2.style.left = `${left}px`;
@@ -1198,6 +1241,25 @@ var WebRemarq = (() => {
1198
1241
  var unsubRoute = null;
1199
1242
  var refreshScheduled = false;
1200
1243
  var elementCache = /* @__PURE__ */ new Map();
1244
+ function describeTarget(el) {
1245
+ var _a, _b, _c, _d;
1246
+ const parts = [];
1247
+ if (el.id) parts.push(`#${el.id}`);
1248
+ const dataAnnotate = el.getAttribute((_a = options.dataAttribute) != null ? _a : "data-annotate");
1249
+ const dataTestId = el.getAttribute("data-testid") || el.getAttribute("data-test") || el.getAttribute("data-cy");
1250
+ if (dataAnnotate) parts.push(`[${dataAnnotate}]`);
1251
+ else if (dataTestId) parts.push(`[${dataTestId}]`);
1252
+ const classes = Array.from(el.classList).filter((c) => !c.match(/^(sc-|css-)/) && !c.match(/^[a-zA-Z0-9]{8,}$/) && !c.match(/__[a-zA-Z0-9]{3,}$/)).slice(0, 2);
1253
+ if (classes.length) parts.push(`.${classes.join(".")}`);
1254
+ let text = "";
1255
+ for (const node of Array.from(el.childNodes)) {
1256
+ if (node.nodeType === Node.TEXT_NODE) text += (_b = node.textContent) != null ? _b : "";
1257
+ }
1258
+ text = text.trim();
1259
+ if (!text && el.children.length <= 2) text = (_d = (_c = el.textContent) == null ? void 0 : _c.trim()) != null ? _d : "";
1260
+ if (text) parts.push(`"${text.slice(0, 30)}"`);
1261
+ return parts.join(" ") || "";
1262
+ }
1201
1263
  function currentRoute() {
1202
1264
  return location.pathname + location.hash;
1203
1265
  }
@@ -1255,7 +1317,6 @@ var WebRemarq = (() => {
1255
1317
  });
1256
1318
  }
1257
1319
  function handleInspectClick(e) {
1258
- var _a, _b;
1259
1320
  if (!inspecting) return;
1260
1321
  const target = e.target;
1261
1322
  if (!target || target.closest("[data-remarq-theme]")) return;
@@ -1267,11 +1328,12 @@ var WebRemarq = (() => {
1267
1328
  popup.show(
1268
1329
  {
1269
1330
  tag: target.tagName.toLowerCase(),
1270
- text: (_b = (_a = target.textContent) == null ? void 0 : _a.trim().slice(0, 30)) != null ? _b : ""
1331
+ text: describeTarget(target)
1271
1332
  },
1272
1333
  {
1273
- top: rect.bottom + 8,
1274
- left: rect.left
1334
+ top: window.scrollY + rect.bottom + 8,
1335
+ left: window.scrollX + rect.left,
1336
+ anchorBottom: window.scrollY + rect.top - 8
1275
1337
  },
1276
1338
  (comment) => {
1277
1339
  const fp = createFingerprint(target, {
@@ -1283,6 +1345,7 @@ var WebRemarq = (() => {
1283
1345
  comment,
1284
1346
  fingerprint: fp,
1285
1347
  route: currentRoute(),
1348
+ viewport: `${window.innerWidth}x${window.innerHeight}`,
1286
1349
  timestamp: Date.now(),
1287
1350
  status: "pending"
1288
1351
  };
@@ -1326,7 +1389,11 @@ var WebRemarq = (() => {
1326
1389
  comment: ann.comment,
1327
1390
  status: ann.status
1328
1391
  },
1329
- { top: rect.bottom + 8, left: rect.left },
1392
+ {
1393
+ top: window.scrollY + rect.bottom + 8,
1394
+ left: window.scrollX + rect.left,
1395
+ anchorBottom: window.scrollY + rect.top - 8
1396
+ },
1330
1397
  {
1331
1398
  onResolve: () => {
1332
1399
  storage.update(ann.id, { status: "resolved" });
@@ -1353,26 +1420,27 @@ var WebRemarq = (() => {
1353
1420
  if (fp.textContent) desc += ` "${fp.textContent}"`;
1354
1421
  if (fp.parentAnchor) desc += ` (${fp.parentAnchor})`;
1355
1422
  if (fp.dataAnnotate) desc += fp.parentAnchor ? ` > ${fp.dataAnnotate}` : ` (${fp.dataAnnotate})`;
1356
- lines.push(`${i + 1}. [${ann.status}] ${desc}: "${ann.comment}"`);
1423
+ const viewport = ann.viewport ? ` @${ann.viewport}` : "";
1424
+ lines.push(`${i + 1}. [${ann.status}]${viewport} ${desc}: "${ann.comment}"`);
1357
1425
  });
1358
1426
  const text = lines.join("\n");
1359
- try {
1360
- navigator.clipboard.writeText(text);
1361
- } catch (e) {
1362
- console.warn("[web-remarq] Clipboard write failed");
1363
- }
1364
- }
1365
- function exportJSON() {
1366
- const data = storage.exportJSON();
1367
- const json = JSON.stringify(data, null, 2);
1368
- const blob = new Blob([json], { type: "application/json" });
1427
+ const blob = new Blob([text], { type: "text/markdown" });
1369
1428
  const url = URL.createObjectURL(blob);
1370
1429
  const a = document.createElement("a");
1371
1430
  a.href = url;
1372
- a.download = `remarq-annotations-${Date.now()}.json`;
1431
+ a.download = `remarq-annotations-${Date.now()}.md`;
1373
1432
  a.click();
1374
1433
  URL.revokeObjectURL(url);
1375
1434
  }
1435
+ function exportJSON() {
1436
+ const data = storage.exportJSON();
1437
+ const json = JSON.stringify(data, null, 2);
1438
+ try {
1439
+ navigator.clipboard.writeText(json);
1440
+ } catch (e) {
1441
+ console.warn("[web-remarq] Clipboard write failed");
1442
+ }
1443
+ }
1376
1444
  function setupMutationObserver() {
1377
1445
  mutationObserver = new MutationObserver((mutations) => {
1378
1446
  for (const m of mutations) {