@ascribed/review 0.2.0 → 0.2.1-next.10

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.
@@ -16,11 +16,12 @@
16
16
  // root, so they sit in the page's reading and tab order.
17
17
  //
18
18
  // Comment bodies are rendered by `markdown.ts`, as DOM nodes.
19
- import { findBlock, goTo, reveal, tabButton } from "../marks/index.js";
19
+ import { findBlock, goTo, reveal, tabButton, titleNodes } from "../marks/index.js";
20
20
  import { anchorKey, formatSource } from "../place/anchor.js";
21
21
  import { renderMarkdown } from "./markdown.js";
22
22
  import { OVERLAY_CSS } from "./style.js";
23
23
  import { authorName, blockText, hasUnsent, initials, linesLabel, listLabel, onRemovedText, plural, relativeTime, whereLabel, } from "./text.js";
24
+ import { DATA_CHANGE, DATA_OVERLAY, DATA_SHOW, DATA_SOURCE, DATA_UI, DATA_VIA, DATA_WAS_SOURCE, ELEMENT_TAB, } from "../names.js";
24
25
  const COLUMN_WIDTH = 250;
25
26
  const COLUMN_GAP = 12;
26
27
  const MARKER_ROOM = "44px";
@@ -255,8 +256,8 @@ class ReviewOverlay {
255
256
  }
256
257
  uiHost(tag) {
257
258
  const host = this.doc.createElement(tag);
258
- host.setAttribute("data-ascribe-ui", "");
259
- host.setAttribute("data-ascribe-overlay", "");
259
+ host.setAttribute(DATA_UI, "");
260
+ host.setAttribute(DATA_OVERLAY, "");
260
261
  return host;
261
262
  }
262
263
  shadow(host) {
@@ -325,29 +326,29 @@ class ReviewOverlay {
325
326
  return this.container().clientWidth >= this.columnAt;
326
327
  }
327
328
  anchorOf(element) {
328
- const source = element.getAttribute("data-ascribe-source");
329
+ const source = element.getAttribute(DATA_SOURCE);
329
330
  if (source === null)
330
331
  return undefined;
331
- const via = (element.getAttribute("data-ascribe-via") ?? "").split(" ").filter(Boolean);
332
+ const via = (element.getAttribute(DATA_VIA) ?? "").split(" ").filter(Boolean);
332
333
  return { source, via };
333
334
  }
334
335
  /** The block an event's target is in: the innermost anchored element. */
335
336
  blockOf(target) {
336
337
  if (!(target instanceof Element))
337
338
  return undefined;
338
- if (target.closest("[data-ascribe-overlay]") && target !== this.toolsHost) {
339
+ if (target.closest(`[${DATA_OVERLAY}]`) && target !== this.toolsHost) {
339
340
  // A marker: the block it's on.
340
- const marker = this.markers.find((m) => m.host === target.closest("[data-ascribe-overlay]"));
341
+ const marker = this.markers.find((m) => m.host === target.closest(`[${DATA_OVERLAY}]`));
341
342
  if (marker)
342
343
  return marker.block;
343
344
  }
344
- const block = target.closest("[data-ascribe-source]");
345
+ const block = target.closest(`[${DATA_SOURCE}]`);
345
346
  return block && this.root.contains(block) ? block : undefined;
346
347
  }
347
348
  /** The block's text as the page shows it, for a comment to quote. */
348
349
  shownText(anchor) {
349
350
  const key = anchorKey(anchor);
350
- for (const el of Array.from(this.root.querySelectorAll("[data-ascribe-source]"))) {
351
+ for (const el of Array.from(this.root.querySelectorAll(`[${DATA_SOURCE}]`))) {
351
352
  const at = this.anchorOf(el);
352
353
  if (at && anchorKey(at) === key)
353
354
  return blockText(el) || undefined;
@@ -355,8 +356,8 @@ class ReviewOverlay {
355
356
  return undefined;
356
357
  }
357
358
  removedElement(anchor) {
358
- for (const el of Array.from(this.root.querySelectorAll("[data-ascribe-was-source]"))) {
359
- if (el.getAttribute("data-ascribe-was-source") === anchor.source)
359
+ for (const el of Array.from(this.root.querySelectorAll(`[${DATA_WAS_SOURCE}]`))) {
360
+ if (el.getAttribute(DATA_WAS_SOURCE) === anchor.source)
360
361
  return el;
361
362
  }
362
363
  return null;
@@ -411,8 +412,8 @@ class ReviewOverlay {
411
412
  }
412
413
  /** Whether what the page shows hides a block: removed text in "as it will be", new text in "as it was". */
413
414
  hiddenByShow(element) {
414
- const show = this.root.getAttribute("data-ascribe-show");
415
- const kind = element.closest("[data-ascribe-change]")?.getAttribute("data-ascribe-change");
415
+ const show = this.root.getAttribute(DATA_SHOW);
416
+ const kind = element.closest(`[${DATA_CHANGE}]`)?.getAttribute(DATA_CHANGE);
416
417
  if (show === "will")
417
418
  return kind === "removed" || kind === "moved-from";
418
419
  if (show === "was")
@@ -422,7 +423,7 @@ class ReviewOverlay {
422
423
  /** Where a block is hidden in the page: an unselected tab or a closed `<details>`. */
423
424
  hiddenIn(element) {
424
425
  for (let node = element.parentElement; node !== null && node !== this.root.parentElement; node = node.parentElement) {
425
- if (node.localName === "ascribe-tab" && node.hidden) {
426
+ if (node.localName === ELEMENT_TAB && node.hidden) {
426
427
  return `In the ${node.getAttribute("label") ?? ""} tab, which isn't showing.`;
427
428
  }
428
429
  if (node.localName === "details" && !node.open) {
@@ -446,7 +447,7 @@ class ReviewOverlay {
446
447
  visibleFor(element) {
447
448
  let shown = element;
448
449
  for (let node = element?.parentElement ?? null; node !== null && node !== this.root; node = node.parentElement) {
449
- if (node.localName === "ascribe-tab" && node.hidden)
450
+ if (node.localName === ELEMENT_TAB && node.hidden)
450
451
  shown = node.parentElement;
451
452
  if (node.localName === "details" && !node.open) {
452
453
  const summary = node.querySelector(":scope > summary");
@@ -502,7 +503,7 @@ class ReviewOverlay {
502
503
  this.root.style.setProperty("margin-inline-end", `${COLUMN_WIDTH + COLUMN_GAP}px`);
503
504
  else
504
505
  this.root.style.removeProperty("margin-inline-end");
505
- for (const el of Array.from(this.root.querySelectorAll("[data-ascribe-source]"))) {
506
+ for (const el of Array.from(this.root.querySelectorAll(`[${DATA_SOURCE}]`))) {
506
507
  if (el.hasAttribute("tabindex"))
507
508
  continue;
508
509
  el.tabIndex = 0;
@@ -550,7 +551,7 @@ class ReviewOverlay {
550
551
  continue;
551
552
  for (let node = element.parentElement; node !== null && node !== this.root; node = node.parentElement) {
552
553
  let on = null;
553
- if (node.localName === "ascribe-tab")
554
+ if (node.localName === ELEMENT_TAB)
554
555
  on = tabButton(node);
555
556
  if (node.localName === "details") {
556
557
  const summary = node.querySelector(":scope > summary");
@@ -950,16 +951,25 @@ class ReviewOverlay {
950
951
  for (const summary of groups[this.filter]) {
951
952
  const { thread, pages } = summary;
952
953
  const first = thread.comments[0];
953
- const page = pages.length > 1 ? `on ${pages.length} pages` : (pages[0]?.title ?? pages[0]?.path ?? "");
954
+ const only = pages.length === 1 ? pages[0] : undefined;
955
+ const page = only
956
+ ? titleNodes(only.formatted_title, only.title ?? only.path, this.doc)
957
+ : pages.length > 1
958
+ ? [`on ${pages.length} pages`]
959
+ : [];
954
960
  // As on its card: a thread with no block is detached, not outdated.
955
961
  const outdated = thread.outdated && thread.detached === undefined;
956
- const where = [listLabel(thread), outdated ? "outdated" : "", page]
957
- .filter(Boolean)
958
- .join(" · ");
962
+ const where = this.el("span", "where");
963
+ where.append([listLabel(thread), outdated ? "outdated" : ""].filter(Boolean).join(" · "));
964
+ if (page.length > 0) {
965
+ if (where.textContent)
966
+ where.append(" · ");
967
+ where.append(...page);
968
+ }
959
969
  const more = thread.comments.length > 1 ? ` (+${thread.comments.length - 1})` : "";
960
970
  const item = this.el("li", "");
961
971
  const jump = this.button("", "", () => this.jump(summary), `jump:${thread.id}`);
962
- jump.append(this.el("span", "where", where), this.el("span", "first", first ? `${authorName(first.author, data.viewer)}: ${oneLine(first.body)}${more}` : ""));
972
+ jump.append(where, this.el("span", "first", first ? `${authorName(first.author, data.viewer)}: ${oneLine(first.body)}${more}` : ""));
963
973
  item.append(jump);
964
974
  list.append(item);
965
975
  }