packages feed

granite 0.7.1.0 → 0.7.1.1

raw patch · 9 files changed

+238/−128 lines, 9 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,8 @@ # Revision history for granite +## 0.7.1.1 -- 2026-05-25+* `GeomTile` honours a continuous `scaleFill` (`SColorContinuous`) via smooth RGB interpolation, and no longer emits a stray category legend entry.+ ## 0.7.1.0 -- 2026-05-25  * Numeric `aesAlpha` mappings are now honoured for points (per-point opacity); previously only the per-layer `defAlpha` was applied.
granite.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               granite-version:            0.7.1.0+version:            0.7.1.1 synopsis:           Easy terminal plotting. description:        A terminal plotting library for quick and easy visualisation. license:            MIT
src/Granite/Render/Pipeline.hs view
@@ -67,6 +67,7 @@     Mapping (..),     PolarAes (..),     PolarDir (..),+    Scale (..),     Scales (..),     Size (..),     Theme (..),@@ -147,12 +148,15 @@             Just t -> not (Text.null t)             Nothing -> False         colorMaps = map (layerColorMap palette (chartData chart)) (chartLayers chart)+        fillCols = case scaleFill (chartScales chart) of+            Just (SColorContinuous cs) -> Just cs+            _ -> Nothing         legendEntries = collectLegend (chartLayers chart) palette colorMaps         hasRightLegend = not (null legendEntries)         box = computePlotBox (chartSize chart) theme hasTitle hasRightLegend False          panels = layoutPanels theme box chart-        panelMarks = concatMap (renderPanel theme palette coord colorMaps) panels+        panelMarks = concatMap (renderPanel theme palette coord colorMaps fillCols) panels          legend = legendMarks theme box legendEntries         title = titleMarks theme box (chartTitle chart)@@ -174,14 +178,24 @@     [ColorSpec] ->     Coord ->     [Maybe [(Text, ColorSpec)]] ->+    Maybe [ColorSpec] ->     PanelSpec ->     [Mark]-renderPanel theme palette coord colorMaps ps =+renderPanel theme palette coord colorMaps fillCols ps =     let proj = buildProjector coord (panelBox ps) (panelXScale ps) (panelYScale ps)         cmap i = if i < length colorMaps then colorMaps !! i else Nothing         layerMarks =             concat-                [ runLayer theme (panelBox ps) proj palette (cmap i) i (panelData ps) layer+                [ runLayer+                    theme+                    (panelBox ps)+                    proj+                    palette+                    (cmap i)+                    fillCols+                    i+                    (panelData ps)+                    layer                 | (i, layer) <- zip [0 :: Int ..] (panelLayers ps)                 ]         axes = axesMarks theme (panelBox ps) coord (panelXScale ps) (panelYScale ps)@@ -414,11 +428,12 @@     Projector ->     [ColorSpec] ->     Maybe [(Text, ColorSpec)] ->+    Maybe [ColorSpec] ->     Int ->     DataFrame ->     Layer ->     [Mark]-runLayer theme box proj palette colorMap ix globalFrame layer =+runLayer theme box proj palette colorMap fillCols ix globalFrame layer =     let frame0 = fromMaybe globalFrame (layerData layer)         framePostStat = applyStat (layerStat layer) (layerMapping layer) frame0         frame = applyPosition (layerPosition layer) (layerMapping layer) framePostStat@@ -456,7 +471,7 @@             GeomHistogram -> drawBars proj frame m col             GeomRibbon -> drawRibbon proj frame m col             GeomErrorbar -> drawErrorbar proj frame m col-            GeomTile -> drawTiles proj frame m col+            GeomTile -> drawTiles proj frame m col fillCols             GeomBoxplot -> drawBoxplot proj frame m col             GeomDensity -> drawDensity proj frame m col             GeomText -> drawText proj frame m col (themeFontSize theme)@@ -580,8 +595,9 @@                     ]         _ -> [] -drawTiles :: Projector -> DataFrame -> Mapping -> Color -> [Mark]-drawTiles proj frame m col =+drawTiles ::+    Projector -> DataFrame -> Mapping -> Color -> Maybe [ColorSpec] -> [Mark]+drawTiles proj frame m col fillCols =     case (resolveNumColumn frame (aesX m), resolveNumColumn frame (aesY m)) of         (Just xs, Just ys) ->             let wX = barWidth xs / 0.8@@ -600,7 +616,9 @@                                     if hi == lo                                         then 0.5                                         else (vs !! i - lo) / (hi - lo)-                             in gradientColor t+                             in case fillCols of+                                    Just cs -> continuousColorFor cs t+                                    Nothing -> gradientColor t                     _ -> col              in [ rectFromCorners                     (proj (x - halfX) (y - halfY))@@ -625,6 +643,26 @@         ix = floor (clamped * fromIntegral n) :: Int      in palette !! ix +{- | Map @t@ in [0,1] to a colour by piecewise-linear RGB interpolation across+the anchor colours (used to honour a continuous 'scaleFill' on tiles).+-}+continuousColorFor :: [ColorSpec] -> Double -> Color+continuousColorFor specs t =+    case map specToColor specs of+        [] -> gradientColor t+        [c] -> c+        colors ->+            let n = length colors+                clamped = max 0 (min 1 t)+                pos = clamped * fromIntegral (n - 1)+                i = min (n - 2) (floor pos)+                frac = pos - fromIntegral i+                Color r1 g1 b1 = colors !! i+                Color r2 g2 b2 = colors !! (i + 1)+                lerp a b =+                    round (fromIntegral a + frac * (fromIntegral b - fromIntegral a))+             in Color (lerp r1 r2) (lerp g1 g2) (lerp b1 b2)+ drawBoxplot :: Projector -> DataFrame -> Mapping -> Color -> [Mark] drawBoxplot proj frame m col =     case ( resolveNumColumn frame (aesX m)@@ -952,6 +990,7 @@   where     entriesFor ix layer cmap         | GeomText <- layerGeom layer = []+        | GeomTile <- layerGeom layer = []         | Just levelColors <- cmap = levelColors         | otherwise =             [(legendName ix layer, palette !! (ix `mod` max 1 (length palette)))]
test/GoldenSpec.hs view
@@ -24,6 +24,7 @@ import Granite.Spec (     BinSpec (..),     Chart (..),+    ColorSpec (..),     ColumnRef (..),     Coord (..),     Facet (..),@@ -266,6 +267,44 @@             , chartSize = SizeChars 30 16             } +-- A continuous-fill heatmap: GeomTile coloured by a numeric column through a+-- 'SColorContinuous' scaleFill (blue -> white -> red). Exercises the continuous+-- tile colour path + the suppressed tile legend.+contHeatmap :: Chart+contHeatmap =+    let coords =+            [ (fromIntegral x, fromIntegral y, fromIntegral (x + y) :: Double)+            | x <- [0 .. 3 :: Int]+            , y <- [0 .. 3 :: Int]+            ]+        df =+            fromColumns+                [ ("x", ColNum [x | (x, _, _) <- coords])+                , ("y", ColNum [y | (_, y, _) <- coords])+                , ("z", ColNum [z | (_, _, z) <- coords])+                ]+        tile =+            (defLayer GeomTile)+                { layerMapping =+                    emptyMapping+                        { aesX = Just (ColumnRef "x")+                        , aesY = Just (ColumnRef "y")+                        , aesFill = Just (ColumnRef "z")+                        }+                , layerStat = StatIdentity+                }+     in emptyChart+            { chartData = df+            , chartLayers = [tile]+            , chartScales =+                defScales+                    { scaleFill =+                        Just (SColorContinuous [Hex "#2166ac", Hex "#f7f7f7", Hex "#b2182b"])+                    }+            , chartTitle = Just "Continuous heatmap"+            , chartSize = SizeChars 40 14+            }+ -- A four-petal rose in polar coordinates: r = |sin(2θ)| sampled at 33 -- angular positions. Locks in the polar projector + polar chrome. polarRose :: Chart@@ -377,6 +416,9 @@          it "pie chart renders to expected SVG output" $             goldenText "pie-basic.svg" (renderChartSvg pieBasic)++        it "continuous-fill heatmap renders to expected SVG output" $+            goldenText "heatmap-continuous.svg" (renderChartSvg contHeatmap)      describe "Sizing" $ do         it "responsive scatter renders to expected SVG output" $
+ test/golden/heatmap-continuous.svg view
@@ -0,0 +1,30 @@+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 224" width="400" height="224" font-family="system-ui, -apple-system, sans-serif">+<rect width="100%" height="100%" fill="white"/>+<line x1="55" y1="196.20" x2="380" y2="196.20" stroke="#ecf0f1" stroke-width="1"/>+<line x1="55" y1="34" x2="55" y2="196.20" stroke="#ecf0f1" stroke-width="1"/>+<text x="100.87" y="211.20" text-anchor="middle" fill="#7f8c8d" font-size="11">0.0</text>+<text x="178.62" y="211.20" text-anchor="middle" fill="#7f8c8d" font-size="11">1.0</text>+<text x="256.38" y="211.20" text-anchor="middle" fill="#7f8c8d" font-size="11">2.0</text>+<text x="334.13" y="211.20" text-anchor="middle" fill="#7f8c8d" font-size="11">3.0</text>+<text x="49" y="176.97" text-anchor="end" fill="#7f8c8d" font-size="11">0.0</text>+<text x="49" y="138.17" text-anchor="end" fill="#7f8c8d" font-size="11">1.0</text>+<text x="49" y="99.36" text-anchor="end" fill="#7f8c8d" font-size="11">2.0</text>+<text x="49" y="60.56" text-anchor="end" fill="#7f8c8d" font-size="11">3.0</text>+<rect x="62.00" y="153.90" width="77.75" height="38.80" fill="#2166ac"/>+<rect x="62.00" y="115.10" width="77.75" height="38.80" fill="#6896c5"/>+<rect x="62.00" y="76.30" width="77.75" height="38.80" fill="#b0c7de"/>+<rect x="62.00" y="37.49" width="77.75" height="38.80" fill="#f7f7f7"/>+<rect x="139.75" y="153.90" width="77.75" height="38.80" fill="#6896c5"/>+<rect x="139.75" y="115.10" width="77.75" height="38.80" fill="#b0c7de"/>+<rect x="139.75" y="76.30" width="77.75" height="38.80" fill="#f7f7f7"/>+<rect x="139.75" y="37.49" width="77.75" height="38.80" fill="#e0adb3"/>+<rect x="217.50" y="153.90" width="77.75" height="38.80" fill="#b0c7de"/>+<rect x="217.50" y="115.10" width="77.75" height="38.80" fill="#f7f7f7"/>+<rect x="217.50" y="76.30" width="77.75" height="38.80" fill="#e0adb3"/>+<rect x="217.50" y="37.49" width="77.75" height="38.80" fill="#c9626f"/>+<rect x="295.25" y="153.90" width="77.75" height="38.80" fill="#f7f7f7"/>+<rect x="295.25" y="115.10" width="77.75" height="38.80" fill="#e0adb3"/>+<rect x="295.25" y="76.30" width="77.75" height="38.80" fill="#c9626f"/>+<rect x="295.25" y="37.49" width="77.75" height="38.80" fill="#b2182b"/>+<text x="217.50" y="26" text-anchor="middle" fill="#7f8c8d" font-size="14">Continuous heatmap</text>+</svg>
test/golden/plotly-heatmap-annotated.svg view
@@ -1,64 +1,62 @@ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 480 256" width="480" height="256" font-family="system-ui, -apple-system, sans-serif"> <rect width="100%" height="100%" fill="white"/>-<line x1="55" y1="228.20" x2="360" y2="228.20" stroke="#ecf0f1" stroke-width="1"/>+<line x1="55" y1="228.20" x2="460" y2="228.20" stroke="#ecf0f1" stroke-width="1"/> <line x1="55" y1="34" x2="55" y2="228.20" stroke="#ecf0f1" stroke-width="1"/>-<text x="91.97" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">0.0</text>-<text x="207.50" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">2.0</text>-<text x="323.03" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">4.0</text>+<text x="104.09" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">0.0</text>+<text x="257.50" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">2.0</text>+<text x="410.91" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">4.0</text> <text x="49" y="208.33" text-anchor="end" fill="#7f8c8d" font-size="11">0.0</text> <text x="49" y="134.77" text-anchor="end" fill="#7f8c8d" font-size="11">2.0</text> <text x="49" y="61.21" text-anchor="end" fill="#7f8c8d" font-size="11">4.0</text>-<rect x="63.09" y="186.27" width="57.77" height="36.78" fill="#2ecc71"/>-<rect x="63.09" y="149.49" width="57.77" height="36.78" fill="#2ecc71"/>-<rect x="63.09" y="112.71" width="57.77" height="36.78" fill="#1abc9c"/>-<rect x="63.09" y="75.93" width="57.77" height="36.78" fill="#3498db"/>-<rect x="63.09" y="39.15" width="57.77" height="36.78" fill="#2980b9"/>-<rect x="120.85" y="186.27" width="57.77" height="36.78" fill="#f1c40f"/>-<rect x="120.85" y="149.49" width="57.77" height="36.78" fill="#f1c40f"/>-<rect x="120.85" y="112.71" width="57.77" height="36.78" fill="#2ecc71"/>-<rect x="120.85" y="75.93" width="57.77" height="36.78" fill="#1abc9c"/>-<rect x="120.85" y="39.15" width="57.77" height="36.78" fill="#3498db"/>-<rect x="178.62" y="186.27" width="57.77" height="36.78" fill="#e74c3c"/>-<rect x="178.62" y="149.49" width="57.77" height="36.78" fill="#e74c3c"/>-<rect x="178.62" y="112.71" width="57.77" height="36.78" fill="#f1c40f"/>-<rect x="178.62" y="75.93" width="57.77" height="36.78" fill="#2ecc71"/>-<rect x="178.62" y="39.15" width="57.77" height="36.78" fill="#1abc9c"/>-<rect x="236.38" y="186.27" width="57.77" height="36.78" fill="#e74c3c"/>-<rect x="236.38" y="149.49" width="57.77" height="36.78" fill="#e74c3c"/>-<rect x="236.38" y="112.71" width="57.77" height="36.78" fill="#f1c40f"/>-<rect x="236.38" y="75.93" width="57.77" height="36.78" fill="#2ecc71"/>-<rect x="236.38" y="39.15" width="57.77" height="36.78" fill="#1abc9c"/>-<rect x="294.15" y="186.27" width="57.77" height="36.78" fill="#e74c3c"/>-<rect x="294.15" y="149.49" width="57.77" height="36.78" fill="#e74c3c"/>-<rect x="294.15" y="112.71" width="57.77" height="36.78" fill="#f1c40f"/>-<rect x="294.15" y="75.93" width="57.77" height="36.78" fill="#2ecc71"/>-<rect x="294.15" y="39.15" width="57.77" height="36.78" fill="#1abc9c"/>-<text x="91.97" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.0</text>-<text x="91.97" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">0.9</text>-<text x="91.97" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">0.5</text>-<text x="91.97" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">0.1</text>-<text x="91.97" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">-0.4</text>-<text x="149.73" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.5</text>-<text x="149.73" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.4</text>-<text x="149.73" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.0</text>-<text x="149.73" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">0.6</text>-<text x="149.73" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.1</text>-<text x="207.50" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.8</text>-<text x="207.50" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.7</text>-<text x="207.50" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.4</text>-<text x="207.50" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">0.9</text>-<text x="207.50" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.4</text>-<text x="265.27" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">2.0</text>-<text x="265.27" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.9</text>-<text x="265.27" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.5</text>-<text x="265.27" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">1.1</text>-<text x="265.27" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.6</text>-<text x="323.03" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.9</text>-<text x="323.03" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.8</text>-<text x="323.03" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.4</text>-<text x="323.03" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">1.0</text>-<text x="323.03" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.5</text>-<text x="207.50" y="26" text-anchor="middle" fill="#7f8c8d" font-size="14">Annotated heatmap</text>-<rect x="375" y="39" width="12" height="12" fill="#3498db"/>-<text x="391" y="49" text-anchor="start" fill="#7f8c8d" font-size="11">series 0</text>+<rect x="65.74" y="186.27" width="76.70" height="36.78" fill="#2ecc71"/>+<rect x="65.74" y="149.49" width="76.70" height="36.78" fill="#2ecc71"/>+<rect x="65.74" y="112.71" width="76.70" height="36.78" fill="#1abc9c"/>+<rect x="65.74" y="75.93" width="76.70" height="36.78" fill="#3498db"/>+<rect x="65.74" y="39.15" width="76.70" height="36.78" fill="#2980b9"/>+<rect x="142.44" y="186.27" width="76.70" height="36.78" fill="#f1c40f"/>+<rect x="142.44" y="149.49" width="76.70" height="36.78" fill="#f1c40f"/>+<rect x="142.44" y="112.71" width="76.70" height="36.78" fill="#2ecc71"/>+<rect x="142.44" y="75.93" width="76.70" height="36.78" fill="#1abc9c"/>+<rect x="142.44" y="39.15" width="76.70" height="36.78" fill="#3498db"/>+<rect x="219.15" y="186.27" width="76.70" height="36.78" fill="#e74c3c"/>+<rect x="219.15" y="149.49" width="76.70" height="36.78" fill="#e74c3c"/>+<rect x="219.15" y="112.71" width="76.70" height="36.78" fill="#f1c40f"/>+<rect x="219.15" y="75.93" width="76.70" height="36.78" fill="#2ecc71"/>+<rect x="219.15" y="39.15" width="76.70" height="36.78" fill="#1abc9c"/>+<rect x="295.85" y="186.27" width="76.70" height="36.78" fill="#e74c3c"/>+<rect x="295.85" y="149.49" width="76.70" height="36.78" fill="#e74c3c"/>+<rect x="295.85" y="112.71" width="76.70" height="36.78" fill="#f1c40f"/>+<rect x="295.85" y="75.93" width="76.70" height="36.78" fill="#2ecc71"/>+<rect x="295.85" y="39.15" width="76.70" height="36.78" fill="#1abc9c"/>+<rect x="372.56" y="186.27" width="76.70" height="36.78" fill="#e74c3c"/>+<rect x="372.56" y="149.49" width="76.70" height="36.78" fill="#e74c3c"/>+<rect x="372.56" y="112.71" width="76.70" height="36.78" fill="#f1c40f"/>+<rect x="372.56" y="75.93" width="76.70" height="36.78" fill="#2ecc71"/>+<rect x="372.56" y="39.15" width="76.70" height="36.78" fill="#1abc9c"/>+<text x="104.09" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.0</text>+<text x="104.09" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">0.9</text>+<text x="104.09" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">0.5</text>+<text x="104.09" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">0.1</text>+<text x="104.09" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">-0.4</text>+<text x="180.80" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.5</text>+<text x="180.80" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.4</text>+<text x="180.80" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.0</text>+<text x="180.80" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">0.6</text>+<text x="180.80" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.1</text>+<text x="257.50" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.8</text>+<text x="257.50" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.7</text>+<text x="257.50" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.4</text>+<text x="257.50" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">0.9</text>+<text x="257.50" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.4</text>+<text x="334.20" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">2.0</text>+<text x="334.20" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.9</text>+<text x="334.20" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.5</text>+<text x="334.20" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">1.1</text>+<text x="334.20" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.6</text>+<text x="410.91" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.9</text>+<text x="410.91" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.8</text>+<text x="410.91" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.4</text>+<text x="410.91" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">1.0</text>+<text x="410.91" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.5</text>+<text x="257.50" y="26" text-anchor="middle" fill="#7f8c8d" font-size="14">Annotated heatmap</text> </svg>
test/golden/plotly-heatmap-annotated.txt view
@@ -1,16 +1,16 @@                                                 -            [90mAnnotated heatmap                   [0m-     [37m│[0m[34m██████[0m[94m█████[0m[96m███████████████████ [0m[94m██         [0m- [90m4.0 [0m[37m│[0m[34m█[0m[95m-0.4[0m[34m█[0m[94m█[0m[95m0.1[0m[94m█[0m[96m██[0m[95m0.4[0m[96m███[0m[95m0.6[0m[96m███[0m[95m0.5[0m[96m██ [0m[94m██[0m[90mseries 0 [0m-     [37m│[0m[34m██████[0m[94m█████[0m[96m███████████████████            [0m-     [37m│[0m[94m██[0m[95m0.1[0m[94m█[0m[96m█[0m[95m0.6[0m[96m█[0m[92m██[0m[95m0.9[0m[92m███[0m[95m1.1[0m[92m███[0m[95m1.0[0m[92m██            [0m-     [37m│[0m[94m██████[0m[96m█████[0m[92m███████████████████            [0m-     [37m│[0m[96m██████[0m[92m█████[0m[93m███████████████████            [0m- [90m2.0 [0m[37m│[0m[96m██[0m[95m0.5[0m[96m█[0m[92m█[0m[95m1.0[0m[92m█[0m[93m██[0m[95m1.4[0m[93m███[0m[95m1.5[0m[93m███[0m[95m1.4[0m[93m██            [0m-     [37m│[0m[96m██████[0m[92m█████[0m[93m███████████████████            [0m-     [37m│[0m[92m██[0m[95m0.9[0m[92m█[0m[93m█[0m[95m1.4[0m[93m█[0m[91m██[0m[95m1.7[0m[91m███[0m[95m1.9[0m[91m███[0m[95m1.8[0m[91m██            [0m-     [37m│[0m[92m██████[0m[93m█████[0m[91m███████████████████            [0m-     [37m│[0m[92m██[0m[95m1.0[0m[92m█[0m[93m█[0m[95m1.5[0m[93m█[0m[91m██[0m[95m1.8[0m[91m███[0m[95m2.0[0m[91m███[0m[95m1.9[0m[91m██            [0m- [90m0.0 [0m[37m│[0m[92m██████[0m[93m█████[0m[91m███████████████████            [0m-     [37m┼───────────────────────────────           [0m-        [90m0.0        2.0         4.0              [0m+                 [90mAnnotated heatmap              [0m+     [37m│[0m[34m████████[0m[94m███████[0m[96m████████████████████████   [0m+ [90m4.0 [0m[37m│[0m[34m██[0m[95m-0.4[0m[34m██[0m[94m███[0m[95m0.1[0m[94m█[0m[96m███[0m[95m0.4[0m[96m█████[0m[95m0.6[0m[96m█████[0m[95m0.5[0m[96m██   [0m+     [37m│[0m[34m████████[0m[94m███████[0m[96m████████████████████████   [0m+     [37m│[0m[94m███[0m[95m0.1[0m[94m██[0m[96m███[0m[95m0.6[0m[96m█[0m[92m███[0m[95m0.9[0m[92m█████[0m[95m1.1[0m[92m█████[0m[95m1.0[0m[92m██   [0m+     [37m│[0m[94m████████[0m[96m███████[0m[92m████████████████████████   [0m+     [37m│[0m[96m████████[0m[92m███████[0m[93m████████████████████████   [0m+ [90m2.0 [0m[37m│[0m[96m███[0m[95m0.5[0m[96m██[0m[92m███[0m[95m1.0[0m[92m█[0m[93m███[0m[95m1.4[0m[93m█████[0m[95m1.5[0m[93m█████[0m[95m1.4[0m[93m██   [0m+     [37m│[0m[96m████████[0m[92m███████[0m[93m████████████████████████   [0m+     [37m│[0m[92m███[0m[95m0.9[0m[92m██[0m[93m███[0m[95m1.4[0m[93m█[0m[91m███[0m[95m1.7[0m[91m█████[0m[95m1.9[0m[91m█████[0m[95m1.8[0m[91m██   [0m+     [37m│[0m[92m████████[0m[93m███████[0m[91m████████████████████████   [0m+     [37m│[0m[92m███[0m[95m1.0[0m[92m██[0m[93m███[0m[95m1.5[0m[93m█[0m[91m███[0m[95m1.8[0m[91m█████[0m[95m2.0[0m[91m█████[0m[95m1.9[0m[91m██   [0m+ [90m0.0 [0m[37m│[0m[92m████████[0m[93m███████[0m[91m████████████████████████   [0m+     [37m┼───────────────────────────────────────── [0m+         [90m0.0            2.0             4.0     [0m
test/golden/plotly-heatmap.svg view
@@ -1,39 +1,37 @@ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 480 256" width="480" height="256" font-family="system-ui, -apple-system, sans-serif"> <rect width="100%" height="100%" fill="white"/>-<line x1="55" y1="228.20" x2="360" y2="228.20" stroke="#ecf0f1" stroke-width="1"/>+<line x1="55" y1="228.20" x2="460" y2="228.20" stroke="#ecf0f1" stroke-width="1"/> <line x1="55" y1="34" x2="55" y2="228.20" stroke="#ecf0f1" stroke-width="1"/>-<text x="91.97" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">0.0</text>-<text x="207.50" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">2.0</text>-<text x="323.03" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">4.0</text>+<text x="104.09" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">0.0</text>+<text x="257.50" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">2.0</text>+<text x="410.91" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">4.0</text> <text x="49" y="208.33" text-anchor="end" fill="#7f8c8d" font-size="11">0.0</text> <text x="49" y="134.77" text-anchor="end" fill="#7f8c8d" font-size="11">2.0</text> <text x="49" y="61.21" text-anchor="end" fill="#7f8c8d" font-size="11">4.0</text>-<rect x="63.09" y="186.27" width="57.77" height="36.78" fill="#2ecc71"/>-<rect x="63.09" y="149.49" width="57.77" height="36.78" fill="#2ecc71"/>-<rect x="63.09" y="112.71" width="57.77" height="36.78" fill="#1abc9c"/>-<rect x="63.09" y="75.93" width="57.77" height="36.78" fill="#3498db"/>-<rect x="63.09" y="39.15" width="57.77" height="36.78" fill="#2980b9"/>-<rect x="120.85" y="186.27" width="57.77" height="36.78" fill="#f1c40f"/>-<rect x="120.85" y="149.49" width="57.77" height="36.78" fill="#f1c40f"/>-<rect x="120.85" y="112.71" width="57.77" height="36.78" fill="#2ecc71"/>-<rect x="120.85" y="75.93" width="57.77" height="36.78" fill="#1abc9c"/>-<rect x="120.85" y="39.15" width="57.77" height="36.78" fill="#3498db"/>-<rect x="178.62" y="186.27" width="57.77" height="36.78" fill="#e74c3c"/>-<rect x="178.62" y="149.49" width="57.77" height="36.78" fill="#e74c3c"/>-<rect x="178.62" y="112.71" width="57.77" height="36.78" fill="#f1c40f"/>-<rect x="178.62" y="75.93" width="57.77" height="36.78" fill="#2ecc71"/>-<rect x="178.62" y="39.15" width="57.77" height="36.78" fill="#1abc9c"/>-<rect x="236.38" y="186.27" width="57.77" height="36.78" fill="#e74c3c"/>-<rect x="236.38" y="149.49" width="57.77" height="36.78" fill="#e74c3c"/>-<rect x="236.38" y="112.71" width="57.77" height="36.78" fill="#f1c40f"/>-<rect x="236.38" y="75.93" width="57.77" height="36.78" fill="#2ecc71"/>-<rect x="236.38" y="39.15" width="57.77" height="36.78" fill="#1abc9c"/>-<rect x="294.15" y="186.27" width="57.77" height="36.78" fill="#e74c3c"/>-<rect x="294.15" y="149.49" width="57.77" height="36.78" fill="#e74c3c"/>-<rect x="294.15" y="112.71" width="57.77" height="36.78" fill="#f1c40f"/>-<rect x="294.15" y="75.93" width="57.77" height="36.78" fill="#2ecc71"/>-<rect x="294.15" y="39.15" width="57.77" height="36.78" fill="#1abc9c"/>-<text x="207.50" y="26" text-anchor="middle" fill="#7f8c8d" font-size="14">Heatmap</text>-<rect x="375" y="39" width="12" height="12" fill="#3498db"/>-<text x="391" y="49" text-anchor="start" fill="#7f8c8d" font-size="11">series 0</text>+<rect x="65.74" y="186.27" width="76.70" height="36.78" fill="#2ecc71"/>+<rect x="65.74" y="149.49" width="76.70" height="36.78" fill="#2ecc71"/>+<rect x="65.74" y="112.71" width="76.70" height="36.78" fill="#1abc9c"/>+<rect x="65.74" y="75.93" width="76.70" height="36.78" fill="#3498db"/>+<rect x="65.74" y="39.15" width="76.70" height="36.78" fill="#2980b9"/>+<rect x="142.44" y="186.27" width="76.70" height="36.78" fill="#f1c40f"/>+<rect x="142.44" y="149.49" width="76.70" height="36.78" fill="#f1c40f"/>+<rect x="142.44" y="112.71" width="76.70" height="36.78" fill="#2ecc71"/>+<rect x="142.44" y="75.93" width="76.70" height="36.78" fill="#1abc9c"/>+<rect x="142.44" y="39.15" width="76.70" height="36.78" fill="#3498db"/>+<rect x="219.15" y="186.27" width="76.70" height="36.78" fill="#e74c3c"/>+<rect x="219.15" y="149.49" width="76.70" height="36.78" fill="#e74c3c"/>+<rect x="219.15" y="112.71" width="76.70" height="36.78" fill="#f1c40f"/>+<rect x="219.15" y="75.93" width="76.70" height="36.78" fill="#2ecc71"/>+<rect x="219.15" y="39.15" width="76.70" height="36.78" fill="#1abc9c"/>+<rect x="295.85" y="186.27" width="76.70" height="36.78" fill="#e74c3c"/>+<rect x="295.85" y="149.49" width="76.70" height="36.78" fill="#e74c3c"/>+<rect x="295.85" y="112.71" width="76.70" height="36.78" fill="#f1c40f"/>+<rect x="295.85" y="75.93" width="76.70" height="36.78" fill="#2ecc71"/>+<rect x="295.85" y="39.15" width="76.70" height="36.78" fill="#1abc9c"/>+<rect x="372.56" y="186.27" width="76.70" height="36.78" fill="#e74c3c"/>+<rect x="372.56" y="149.49" width="76.70" height="36.78" fill="#e74c3c"/>+<rect x="372.56" y="112.71" width="76.70" height="36.78" fill="#f1c40f"/>+<rect x="372.56" y="75.93" width="76.70" height="36.78" fill="#2ecc71"/>+<rect x="372.56" y="39.15" width="76.70" height="36.78" fill="#1abc9c"/>+<text x="257.50" y="26" text-anchor="middle" fill="#7f8c8d" font-size="14">Heatmap</text> </svg>
test/golden/plotly-heatmap.txt view
@@ -1,16 +1,16 @@                                                 -                 [90mHeatmap                        [0m-     [37m│[0m[34m██████[0m[94m█████[0m[96m███████████████████ [0m[94m██         [0m- [90m4.0 [0m[37m│[0m[34m██████[0m[94m█████[0m[96m███████████████████ [0m[94m██[0m[90mseries 0 [0m-     [37m│[0m[34m██████[0m[94m█████[0m[96m███████████████████            [0m-     [37m│[0m[94m██████[0m[96m█████[0m[92m███████████████████            [0m-     [37m│[0m[94m██████[0m[96m█████[0m[92m███████████████████            [0m-     [37m│[0m[96m██████[0m[92m█████[0m[93m███████████████████            [0m- [90m2.0 [0m[37m│[0m[96m██████[0m[92m█████[0m[93m███████████████████            [0m-     [37m│[0m[96m██████[0m[92m█████[0m[93m███████████████████            [0m-     [37m│[0m[92m██████[0m[93m█████[0m[91m███████████████████            [0m-     [37m│[0m[92m██████[0m[93m█████[0m[91m███████████████████            [0m-     [37m│[0m[92m██████[0m[93m█████[0m[91m███████████████████            [0m- [90m0.0 [0m[37m│[0m[92m██████[0m[93m█████[0m[91m███████████████████            [0m-     [37m┼───────────────────────────────           [0m-        [90m0.0        2.0         4.0              [0m+                      [90mHeatmap                   [0m+     [37m│[0m[34m████████[0m[94m███████[0m[96m████████████████████████   [0m+ [90m4.0 [0m[37m│[0m[34m████████[0m[94m███████[0m[96m████████████████████████   [0m+     [37m│[0m[34m████████[0m[94m███████[0m[96m████████████████████████   [0m+     [37m│[0m[94m████████[0m[96m███████[0m[92m████████████████████████   [0m+     [37m│[0m[94m████████[0m[96m███████[0m[92m████████████████████████   [0m+     [37m│[0m[96m████████[0m[92m███████[0m[93m████████████████████████   [0m+ [90m2.0 [0m[37m│[0m[96m████████[0m[92m███████[0m[93m████████████████████████   [0m+     [37m│[0m[96m████████[0m[92m███████[0m[93m████████████████████████   [0m+     [37m│[0m[92m████████[0m[93m███████[0m[91m████████████████████████   [0m+     [37m│[0m[92m████████[0m[93m███████[0m[91m████████████████████████   [0m+     [37m│[0m[92m████████[0m[93m███████[0m[91m████████████████████████   [0m+ [90m0.0 [0m[37m│[0m[92m████████[0m[93m███████[0m[91m████████████████████████   [0m+     [37m┼───────────────────────────────────────── [0m+         [90m0.0            2.0             4.0     [0m