diff --git a/CHANGELOG.md b/CHANGELOG.md index 9481b49..efc0ece 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - feat: `labs()` fields default to `auto`; pass `none` to suppress an axis or legend title and reclaim the space it reserved. (#12) - feat: `element-blank()` on a text surface (axis, plot, or legend title) collapses the space the text would reserve. (#12) - feat: `width`/`height` accept `auto` to fill the available space of a bounded container. (#10) +- fix: `coord-flip(reverse: true)` preserves a `log10`/`sqrt` axis transform instead of overwriting it. (#42) - fix: `geom-col()` on a continuous x with a single distinct value no longer panics when inferring the bar width. (#41) - fix: `log10`/`sqrt` scales validate user `limits` and report a clear error for non-positive bounds. (#40) - fix: `geom-smooth()` honours the `level` argument when sizing the confidence band instead of always using 95%. (#39) diff --git a/src/render.typ b/src/render.typ index d415095..9511e1b 100644 --- a/src/render.typ +++ b/src/render.typ @@ -1969,7 +1969,7 @@ if x.type == "discrete" { new-y.insert("reverse", true) } else if x.type == "continuous" { - new-y.insert("transform", "reverse") + new-y.insert("reverse", not new-y.at("reverse", default: false)) } trained.insert("y", new-y) trained diff --git a/src/scale/train.typ b/src/scale/train.typ index 588fd43..463b353 100644 --- a/src/scale/train.typ +++ b/src/scale/train.typ @@ -521,7 +521,10 @@ (_to-stat(trained, d-lo), _to-stat(trained, d-hi)) } let (r-lo, r-hi) = range - let target = if transform == "reverse" { + // `reverse` rides alongside the numeric transform rather than replacing it, + // so a log10/sqrt axis can also be reversed (e.g. under coord-flip). + let reverse = transform == "reverse" or trained.at("reverse", default: false) + let target = if reverse { (r-hi, r-lo) } else { (r-lo, r-hi) } map-continuous(_to-stat(trained, value), (t-lo, t-hi), target) diff --git a/tests/unit/test-coord-flip.typ b/tests/unit/test-coord-flip.typ index 3917a43..8fafa08 100644 --- a/tests/unit/test-coord-flip.typ +++ b/tests/unit/test-coord-flip.typ @@ -49,10 +49,21 @@ #let cc-flipped = _apply-flip(cc, c1) #assert.eq(cc-flipped.y.at("transform", default: "identity"), "identity") -// Explicit `reverse: true` reverses a continuous post-flip y via the -// existing transform path. +// Explicit `reverse: true` reverses a continuous post-flip y via a `reverse` +// flag, leaving any numeric transform intact. #let cc-rev = _apply-flip(cc, coord-flip(reverse: true)) -#assert.eq(cc-rev.y.transform, "reverse") +#assert.eq(cc-rev.y.reverse, true) +#assert.eq(cc-rev.y.at("transform", default: "identity"), "identity") + +// A log10 x keeps its transform under flip + reverse (regression: the +// reverse used to overwrite the numeric transform with "reverse"). +#let cc-log = ( + x: (type: "continuous", domain: (0, 3), transform: "log10"), + y: (type: "continuous", domain: (0, 1)), +) +#let cc-log-rev = _apply-flip(cc-log, coord-flip(reverse: true)) +#assert.eq(cc-log-rev.y.transform, "log10") +#assert.eq(cc-log-rev.y.reverse, true) #let untouched = _apply-flip(trained, (kind: "coord", coord: "cartesian")) #assert.eq(untouched.x.type, "discrete")