slidemind 0.3.5 → 0.3.12

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/src/pptx/tags.mjs CHANGED
@@ -670,7 +670,56 @@ export function computeProjection(files, slidePathOverride) {
670
670
  fill: paint.fill,
671
671
  line: paint.line,
672
672
  mediaSha256: parseMediaSha(files, slidePath, raw.xml),
673
+ // Always null here — see the CHART HASH note below. The FIELD is mirrored
674
+ // so both implementations serialize the same key set (the parity fixtures
675
+ // are byte-compared); the VALUE is the one thing this mirror cannot
676
+ // reproduce.
677
+ chart: null,
673
678
  });
674
679
  }
675
680
  return { v: 1, shapes };
676
681
  }
682
+
683
+ // ---------------------------------------------------------------------------
684
+ // CHART HASH — the one non-parity field, deliberately
685
+ // ---------------------------------------------------------------------------
686
+ //
687
+ // The add-in's `ProjectionShape.chart` is sha256 over the CANONICAL ChartSpec of
688
+ // a chart graphic frame (`native-charts`, task 7.4). It is a SPEC hash, never a
689
+ // hash of the chart part's XML, and that is not a detail: PowerPoint
690
+ // re-serializes a chart part on every save and materializes its own defaults
691
+ // into it, so an XML hash would report drift on a deck nobody touched. Only
692
+ // `canonicalize(spec)` is stable across that round trip.
693
+ //
694
+ // Producing it therefore needs the whole chart READER (`c:` + `cx:` families,
695
+ // ~3k lines of DOM code) plus the canonicaliser. This file is regex-only and
696
+ // `src/pptx/` is deliberately dependency-free — no DOM parser ships here — so a
697
+ // hand-port would be a second source of truth for chart semantics that WILL
698
+ // drift from the add-in's. It is not written, on purpose.
699
+ //
700
+ // What that costs, stated plainly: this mirror cannot tell that a chart's data
701
+ // or styling changed. Everything else about the slide — geometry, text, fill,
702
+ // line, media — still compares exactly. The consumers below therefore drop the
703
+ // field from BOTH sides before comparing, so a chart can never produce a FALSE
704
+ // "someone edited this" refusal; the price is that a chart-ONLY edit is
705
+ // invisible to the CLI's guard (the add-in's own drift check, which does have
706
+ // the reader, still catches it on the next push).
707
+ //
708
+ // Closing it properly means giving this repo the reader as a GENERATED artifact
709
+ // built from the add-in's TypeScript — never a hand-written copy.
710
+
711
+ /**
712
+ * A projection with every `chart` hash dropped, for comparing an add-in-written
713
+ * baseline against a projection computed HERE. Both sides go through it, so the
714
+ * comparison stays symmetric.
715
+ */
716
+ export function withoutChartHashes(projection) {
717
+ if (!projection?.shapes) return projection;
718
+ return {
719
+ ...projection,
720
+ shapes: projection.shapes.map((shape) => {
721
+ const { chart: _unreadableHere, ...rest } = shape;
722
+ return rest;
723
+ }),
724
+ };
725
+ }