@pptx-studio/validate 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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @pptx-studio/validate
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - db00af0: `tableBackground` now returns the table background's two layers, `{ fill, effects }`, each taken
8
+ from `a:tblPr` where it writes one and from the style's `tblBg` otherwise. An empty `a:effectLst` in
9
+ `a:tblPr` removes the style's effect, as PowerPoint draws it, and `themedEffects` follows an
10
+ `effectRef` into the theme. `tableCellDiagonals` gives a cell's diagonals as drawn: the anchor's
11
+ own `a:lnTlToBr` and `a:lnBlToTr` across its whole span, a covered position's never, and swapped in a
12
+ right-to-left table.
13
+
14
+ validate's `V034` also warns on every line a covered cell writes, which PowerPoint keeps on save
15
+ and never draws, and on a border written under a position no `a:tc` reached.
16
+
3
17
  ## 0.4.0
4
18
 
5
19
  ### Minor Changes
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/errors.ts","../src/rules/rules.ts","../src/report/location.ts","../src/report/report.ts","../src/context.ts","../src/validate.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/errors.ts","../src/rules/rules.ts","../src/report/location.ts","../src/report/report.ts","../src/context.ts","../src/validate.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -318,7 +318,7 @@ const RULES = [
318
318
  severity: "warning",
319
319
  evidence: "measured",
320
320
  title: "a border a cell writes is the one PowerPoint draws on that edge",
321
- why: "A grid edge belongs to two cells, and each may write a line for it. C9 drew direct borders, on plain and merged cells, under seven built-ins and the default grid: PowerPoint draws an edge from the cell above or to the left - its `a:lnB` or `a:lnR`, or the style where it writes none - where that cell, merged or not, has its anchor level with the edge. Otherwise the cell below or to the right draws its own `a:lnT` or `a:lnL` where its anchor is level with the edge, and elsewhere the cell above or to the left keeps it. When PowerPoint sets a border itself it writes every side alike. The deck opens without a word, which is why this is a warning: the file says one border and PowerPoint draws another."
321
+ why: "A grid edge belongs to two cells, and each may write a line for it. C9 drew direct borders, on plain and merged cells, under seven built-ins and the default grid: PowerPoint draws an edge from the cell above or to the left - its `a:lnB` or `a:lnR`, or the style where it writes none - where that cell, merged or not, has its anchor level with the edge. Otherwise the cell below or to the right draws its own `a:lnT` or `a:lnL` where its anchor is level with the edge, and elsewhere the cell above or to the left keeps it. A position no `a:tc` reached owns its edges as a cell writing nothing does, and a covered cell’s own lines are never drawn, though PowerPoint keeps them on save. When PowerPoint sets a border itself it writes every side alike. The deck opens without a word, which is why this is a warning: the file says one border and PowerPoint draws another."
322
322
  }
323
323
  ];
324
324
  const BY_ID = new Map(RULES.map((rule) => [rule.id, rule]));
@@ -1487,6 +1487,20 @@ function lineOf(cell, local) {
1487
1487
  const tcPr = childElements(cell).find((child) => child.local === "tcPr");
1488
1488
  return tcPr === void 0 ? void 0 : childElements(tcPr).find((child) => child.local === local);
1489
1489
  }
1490
+ /** Each line a covered cell's own `a:tcPr` writes that would draw something: none is drawn (C9). */
1491
+ function reportCovered(ctx, part, cell, [r, c], owner) {
1492
+ const tcPr = childElements(cell).find((child) => child.local === "tcPr");
1493
+ const lines = tcPr === void 0 ? [] : childElements(tcPr).filter((child) => LINE_TAGS.has(child.local) && !drawsNothing(child));
1494
+ for (const written of lines) ctx.add("V034", elementLocation(part, written), `cell (${String(r + 1)}, ${String(c + 1)}) writes <a:${written.local}>, but it is covered by the span of cell (${String(owner.row + 1)}, ${String(owner.col + 1)}), and PowerPoint never draws a covered cell’s own lines - measured in C9.`);
1495
+ }
1496
+ const LINE_TAGS = /* @__PURE__ */ new Set([
1497
+ "lnL",
1498
+ "lnR",
1499
+ "lnT",
1500
+ "lnB",
1501
+ "lnTlToBr",
1502
+ "lnBlToTr"
1503
+ ]);
1490
1504
  /** The grid position across segment `k` of a cell's `side`, the cell anchored at (r, c). */
1491
1505
  function acrossOf(side, r, c, owner, k) {
1492
1506
  if (side === "lnT") return [r - 1, c + k];
@@ -1526,9 +1540,9 @@ const SIDES = [
1526
1540
  }
1527
1541
  ];
1528
1542
  /**
1529
- * A border a cell writes that PowerPoint draws from the cell across the edge: the cell before owns a
1530
- * segment where its anchor is level with it, else the cell after where its is, else the cell before
1531
- * (C9, ADR 0064). PowerPoint's own writer writes every side alike, so this never fires on its output.
1543
+ * A border a cell writes that PowerPoint draws from the cell or empty position across the edge, and
1544
+ * any line a covered cell writes (C9, ADR 0064). PowerPoint's own writer writes every side alike and
1545
+ * leaves a covered cell's `a:tcPr` empty, so this never fires on its output.
1532
1546
  */
1533
1547
  function v034TableBorders(ctx) {
1534
1548
  forEachElement(ctx, (part, element) => {
@@ -1539,7 +1553,11 @@ function v034TableBorders(ctx) {
1539
1553
  const grid = owners(cells, cols);
1540
1554
  for (const [r, line] of cells.entries()) for (const [c, cell] of line.entries()) {
1541
1555
  const owner = grid[r]?.[c];
1542
- if (owner?.row !== r || owner.col !== c) continue;
1556
+ if (owner === null || owner === void 0) continue;
1557
+ if (owner.row !== r || owner.col !== c) {
1558
+ reportCovered(ctx, part, cell, [r, c], owner);
1559
+ continue;
1560
+ }
1543
1561
  for (const s of SIDES) {
1544
1562
  const written = lineOf(cell, s.side);
1545
1563
  if (written === void 0) continue;
@@ -1547,12 +1565,19 @@ function v034TableBorders(ctx) {
1547
1565
  for (let k = 0; k < reach; k++) {
1548
1566
  const [nr, nc] = acrossOf(s.side, r, c, owner, k);
1549
1567
  const other = grid[nr]?.[nc];
1550
- if (other === null || other === void 0) continue;
1551
- const otherLevel = s.across === "cols" ? other.col === nc : other.row === nr;
1568
+ if (other === void 0) continue;
1569
+ const at = other ?? {
1570
+ row: nr,
1571
+ col: nc,
1572
+ rows: 1,
1573
+ cols: 1
1574
+ };
1575
+ const otherLevel = s.across === "cols" ? at.col === nc : at.row === nr;
1552
1576
  if (!(s.after ? otherLevel || k > 0 : k > 0 && otherLevel)) continue;
1553
- const drawn = lineOf(cells[other.row][other.col], s.facing);
1577
+ const drawn = other === null ? void 0 : lineOf(cells[at.row][at.col], s.facing);
1554
1578
  if (drawn !== void 0 && alike(drawn, written)) continue;
1555
- ctx.add("V034", elementLocation(part, written), `cell (${String(r + 1)}, ${String(c + 1)}) writes <a:${s.side}>, but ${s.where} ${String((s.across === "cols" ? nc : nr) + 1)} PowerPoint draws the <a:${s.facing}> of cell (${String(other.row + 1)}, ${String(other.col + 1)}), which writes ${drawn === void 0 ? "none" : "a different one"} - measured in C9.`);
1579
+ const whose = other === null ? `position (${String(nr + 1)}, ${String(nc + 1)}), which no <a:tc> reached` : `cell (${String(at.row + 1)}, ${String(at.col + 1)}), which writes ` + (drawn === void 0 ? "none" : "a different one");
1580
+ ctx.add("V034", elementLocation(part, written), `cell (${String(r + 1)}, ${String(c + 1)}) writes <a:${s.side}>, but ${s.where} ${String((s.across === "cols" ? nc : nr) + 1)} PowerPoint draws the <a:${s.facing}> of ${whose} - measured in C9.`);
1556
1581
  break;
1557
1582
  }
1558
1583
  }