inkplot 0.3.0 → 0.3.2

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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.codespellignore +0 -0
  3. data/.yamllint +16 -0
  4. data/CHANGELOG.md +16 -1
  5. data/LICENSE.txt +1 -1
  6. data/README.md +43 -67
  7. data/bench/inkplot.rb +12 -3
  8. data/docs/index.html +31 -0
  9. data/examples/gallery/01-line.svg +1 -1
  10. data/examples/gallery/02-line-gaps.svg +1 -1
  11. data/examples/gallery/03-series.svg +1 -1
  12. data/examples/gallery/09-histogram.svg +1 -0
  13. data/examples/gallery/12-time.svg +1 -0
  14. data/examples/gallery/13-annotations.svg +1 -0
  15. data/examples/gallery/14-dark-theme.svg +1 -0
  16. data/examples/gallery/15-category-labels.svg +1 -0
  17. data/examples/gallery/16-custom-bins.svg +1 -0
  18. data/examples/gallery/17-connected-gaps.svg +1 -0
  19. data/examples/gallery/18-step-series.svg +1 -0
  20. data/examples/gallery/19-combined-marks.svg +1 -0
  21. data/examples/gallery/20-scatter-sizes.svg +1 -0
  22. data/examples/gallery/README.md +7 -7
  23. data/examples/gallery.rb +26 -44
  24. data/lib/inkplot/core.rb +351 -146
  25. data/lib/inkplot/renderers/png.rb +390 -0
  26. data/lib/inkplot/renderers/svg.rb +3 -1
  27. data/lib/inkplot/version.rb +1 -1
  28. data/lib/inkplot.rb +3 -3
  29. data/sig/inkplot.rbs +7 -6
  30. data/test/snapshots/inkplot/01-line.png +0 -0
  31. data/test/snapshots/inkplot/02-line-gaps.png +0 -0
  32. data/test/snapshots/inkplot/03-series.png +0 -0
  33. data/test/snapshots/inkplot/04-scatter.png +0 -0
  34. data/test/snapshots/inkplot/05-bars.png +0 -0
  35. data/test/snapshots/inkplot/06-horizontal-bars.png +0 -0
  36. data/test/snapshots/inkplot/07-grouped-bars.png +0 -0
  37. data/test/snapshots/inkplot/08-stacked-bars.png +0 -0
  38. data/test/snapshots/inkplot/09-histogram.png +0 -0
  39. data/test/snapshots/inkplot/10-area.png +0 -0
  40. data/test/snapshots/inkplot/11-step.png +0 -0
  41. data/test/snapshots/inkplot/12-time.png +0 -0
  42. data/test/snapshots/inkplot/13-annotations.png +0 -0
  43. data/test/snapshots/inkplot/14-dark-theme.png +0 -0
  44. data/test/snapshots/inkplot/15-category-labels.png +0 -0
  45. data/test/snapshots/inkplot/16-custom-bins.png +0 -0
  46. data/test/snapshots/inkplot/17-connected-gaps.png +0 -0
  47. data/test/snapshots/inkplot/18-step-series.png +0 -0
  48. data/test/snapshots/inkplot/19-combined-marks.png +0 -0
  49. data/test/snapshots/inkplot/20-scatter-sizes.png +0 -0
  50. metadata +41 -18
  51. data/examples/gallery/09-signed-stack.svg +0 -1
  52. data/examples/gallery/12-histogram.svg +0 -1
  53. data/examples/gallery/13-log-scale.svg +0 -1
  54. data/examples/gallery/14-time-axis.svg +0 -1
  55. data/examples/gallery/15-category-order.svg +0 -1
  56. data/examples/gallery/16-dark-theme.svg +0 -1
  57. data/examples/gallery/17-annotations.svg +0 -1
  58. data/examples/gallery/18-combo.svg +0 -1
  59. data/examples/gallery/19-legend-position.svg +0 -1
  60. data/examples/gallery/20-long-categories.svg +0 -1
  61. data/lib/inkplot/renderers/raster.rb +0 -322
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90a3ec94d835a8c52be1645190c450486b74e3d69e69f9c7a32759c52cd9fbad
4
- data.tar.gz: 670616432fd769febb36b31b338d506e58abb41fbdc32820fd0b97b0df9c2ec3
3
+ metadata.gz: 570091faeb52297dab7d74cc8bf77a37f32f69b9f8bc99e8d24df631e43082c2
4
+ data.tar.gz: 8f69487642335b444a7a50961e077f216a7cb269947749cc463449e4b19d72c0
5
5
  SHA512:
6
- metadata.gz: 23eef7bbe84575c0b7d32626a36d880de2a7e5c408791df60b9b0675a8a561bf9c58aa2aea0d28dd0653c126ce9746672bfd83ea734480a84cfbf74af334a861
7
- data.tar.gz: c80647ebc946d60e8ec623010735aea0f71e922c296d2777265251ad8766a2fef0d3848326ed735d48ca72c0d797cf8eda00468a2dc76cad36c22fa85e9c358c
6
+ metadata.gz: 279de78c919ae89c44b923e0d3880399b22a40040c84dd9b2d7d4e74e8abf0e263d7a8bd378b4d7e40b813e473885da31b14e9ebaf2c363222e983b1094034d1
7
+ data.tar.gz: cf1e3a1d032bee953d177eba082a0b3b13e96621a15363f2c586710d5e7453e73eb2eded277be046dc839bf985700fceccc0d749be99c3e1fde7595442a8945c
data/.codespellignore ADDED
File without changes
data/.yamllint ADDED
@@ -0,0 +1,16 @@
1
+ extends: default
2
+ ignore: |
3
+ build/
4
+ node_modules/
5
+ runtime/build/
6
+ tmp/
7
+ **/*.dSYM/**
8
+
9
+ rules:
10
+ comments:
11
+ min-spaces-from-content: 1
12
+ document-start: disable
13
+ line-length:
14
+ max: 200
15
+ truthy:
16
+ check-keys: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.2] - 2026-09-26
4
+
5
+ - Keep histogram scales finite at extreme numeric values and distinguish very small chart values on axes.
6
+ - Report when chart dimensions cannot fit labels or a legend.
7
+
8
+ ## [0.3.1] - 2026-09-25
9
+
10
+ - Make PNG rendering and the expanded chart features available in the installed gem.
11
+ - Fix installation of optional renderer dependencies from RubyGems.
12
+
3
13
  ## [0.3.0] - 2026-09-25
4
14
 
5
- - Implement SVG and PNG chart rendering, scales, annotations, terminal sparklines, REPL adaptation, and the 20-chart gallery.
15
+ - Add PNG rendering, time scales, histograms, category labels, and text annotations.
16
+ - Expand the gallery to 20 charts and add chart-to-Inlay integration.
17
+
18
+ ## [0.1.0] - 2026-09-25
19
+
20
+ Initial release
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2026 ydah
3
+ Copyright (c) 2026 Yudai Takada
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <h1 align="center">Inkplot</h1>
2
2
 
3
- <p align="center">Ruby charts, drawn as portable SVG or PNG.</p>
3
+ <p align="center">Build clear SVG and PNG charts from plain Ruby data.</p>
4
4
 
5
5
  <p align="center">
6
6
  <a href="https://github.com/rbgfx/inkplot/actions/workflows/main.yml"><img src="https://github.com/rbgfx/inkplot/actions/workflows/main.yml/badge.svg" alt="CI"></a>
@@ -8,35 +8,14 @@
8
8
  <a href="LICENSE.txt"><img src="https://img.shields.io/badge/license-MIT-750014.svg" alt="MIT license"></a>
9
9
  </p>
10
10
 
11
- Line, bar, scatter, area, step, and histogram charts with clean defaults. SVG runs on Ruby alone; optional pure Ruby image gems add PNG output and REPL display.
12
-
13
- ## At a glance
14
-
15
- - **No runtime dependencies for SVG** and no native graphics libraries.
16
- - **Useful defaults:** automatic linear, logarithmic, category, and time scales; readable ticks, legends, and light or dark themes.
17
- - **Ruby data in:** arrays, hashes, CSV tables, and records with string or symbol keys.
18
- - **Flexible output:** SVG strings, PNG bytes, `Tessel::Image`, files, and terminal sparklines.
19
- - **Optional adapters:** Tessel and Glyphic for PNG; Inlay for IRB, Pry, and IRuby.
11
+ Inkplot draws line, scatter, bar, area, histogram, and step charts without runtime dependencies. SVG output uses only Ruby's standard library; optional PNG output needs `tessel` and `glyphic`.
20
12
 
21
13
  ## Install
22
14
 
23
- Until the first RubyGems release, add Inkplot from GitHub:
24
-
25
- ```ruby
26
- gem "inkplot", github: "rbgfx/inkplot"
27
- ```
28
-
29
- SVG needs only Inkplot. For PNG output, add the optional render dependencies:
15
+ Install the gem:
30
16
 
31
- ```ruby
32
- gem "tessel", github: "rbgfx/tessel"
33
- gem "glyphic", github: "rbgfx/glyphic"
34
- ```
35
-
36
- Glyphic's built-in font covers ASCII. For other scripts, set a TrueType font:
37
-
38
- ```ruby
39
- Inkplot.config.font = "/path/to/font.ttf"
17
+ ```sh
18
+ gem install inkplot
40
19
  ```
41
20
 
42
21
  ## Quick start
@@ -44,77 +23,74 @@ Inkplot.config.font = "/path/to/font.ttf"
44
23
  ```ruby
45
24
  require "inkplot"
46
25
 
47
- chart = Inkplot.line([3, 1, 4, 1, 5, 9, 2, 6], title: "A small series")
26
+ chart = Inkplot.line([3, 1, 4, 1, 5, 9], title: "A small series")
48
27
  chart.save("series.svg")
49
- chart.save("series.png", width: 800, height: 450, scale: 2)
50
28
  ```
51
29
 
52
- Use CSV or records directly. Keys can be symbols or strings; `color:` splits records into labeled series.
53
-
54
- ```ruby
55
- require "csv"
56
-
57
- rows = CSV.parse(File.read("sales.csv"), headers: true)
58
- chart = Inkplot.line(rows, x: "month", y: "sales", color: "region", title: "Monthly sales")
59
- chart.to_svg # => standalone SVG string
60
- ```
61
-
62
- The builder API combines marks, scales, and annotations:
30
+ Use the builder to combine series and configure axes:
63
31
 
64
32
  ```ruby
65
33
  chart = Inkplot.plot(width: 720, height: 420, theme: :dark) do |plot|
66
- plot.title "Request latency"
67
- plot.x_axis label: "Time", type: :time
68
- plot.y_axis label: "Milliseconds", scale: :log, min: 1
69
- plot.line times, p50, label: "p50"
70
- plot.line times, p99, label: "p99", dash: true
71
- plot.hline 200, label: "SLO", color: :red
72
- plot.legend position: :top_right
34
+ plot.title "Quarterly requests"
35
+ plot.x_axis(label: "Quarter")
36
+ plot.y_axis(label: "Requests", min: 0)
37
+ plot.line(%w[Q1 Q2 Q3 Q4], [18, 23, 28, 36], label: "Current")
38
+ plot.line(%w[Q1 Q2 Q3 Q4], [14, 19, 21, 30], label: "Previous", dash: true)
39
+ plot.hline(25, label: "Target")
40
+ plot.legend(position: :top_right)
73
41
  end
74
- ```
75
42
 
76
- `Inkplot.bar(data, horizontal: true)` draws horizontal bars. `Inkplot.histogram(values, bins: :auto)` chooses bins with Freedman–Diaconis, falling back to Sturges when the interquartile range is zero. Builder methods also provide grouped and signed stacked bars, areas, steps, sized scatter points, and text or line annotations.
43
+ svg = chart.to_svg
44
+ ```
77
45
 
78
- ## Gallery
46
+ ## PNG output
79
47
 
80
- Twenty runnable chart examples and SVG previews are in the [gallery](examples/gallery/README.md). Rebuild the SVGs with:
48
+ PNG rendering is optional and uses the pure Ruby [Tessel](https://github.com/rbgfx/tessel) and [Glyphic](https://github.com/rbgfx/glyphic) gems:
81
49
 
82
50
  ```sh
83
- ruby examples/gallery.rb
51
+ gem install tessel glyphic
52
+ ```
53
+
54
+ ```ruby
55
+ chart = Inkplot.line([3, 1, 4, 1, 5, 9], title: "A small series")
56
+ chart.save("series.png", scale: 2)
57
+ png_bytes = chart.to_png
84
58
  ```
85
59
 
86
- ## REPL and terminal
60
+ Set `Inkplot.config.font` to a TrueType font path for Unicode text. Without a font path, PNG output uses Glyphic's small ASCII bitmap font; SVG uses the viewer's system fonts.
61
+
62
+ ## Data and output
87
63
 
88
- When [Inlay](https://github.com/rbgfx/inlay) is loaded, Inkplot's `to_inlay` adapter returns SVG plus a lazy PNG fallback. A terminal without an inline image protocol can use:
64
+ Charts accept arrays, hashes, CSV tables, and records with string or symbol keys. Scales include linear, logarithmic, time (`Time` and `Date`), and ordered categories. Light and dark themes, grouped and stacked bars, annotations, and terminal sparklines are included.
89
65
 
90
66
  ```ruby
91
- puts Inkplot.sparkline([3, 1, 4, 1, 5, 9, 2, 6]) # => "▃▁▄▁▅█▂▅"
67
+ latencies = [12, 13, 15, 15, 18, 21, 26, 42]
68
+ Inkplot.histogram(latencies, bins: :auto, x_label: "ms").save("latencies.svg")
92
69
  ```
93
70
 
94
- ## Performance
71
+ For dated data, configure the x axis with `type: :time`. `plot.annotate(x, y, "text")` places text at a data point; `hline` and `vline` can also carry labels.
95
72
 
96
- Reference run on Ruby 4.0.6 with YJIT, at 640×360: a 1,000-point line rendered to SVG in 3 ms, the same chart to PNG in 235 ms, and a 10,000-point scatter plot to PNG in 668 ms. These single-run measurements met the design targets of 50 ms, 300 ms, and 1 second respectively; see `bench/inkplot.rb` to rerun them.
73
+ The [gallery](examples/gallery/README.md) contains 20 runnable examples. Regenerate its SVG previews with:
74
+
75
+ ```sh
76
+ ruby examples/gallery.rb
77
+ ```
97
78
 
98
79
  ## API contracts
99
80
 
100
- - Chart dimensions must be at least 120×100 pixels. Paired x/y vectors must have equal lengths.
101
- - Non-finite y values are treated as gaps. `gaps: :connect` connects line segments across them.
102
- - Explicit axis limits must be valid and ordered. Log axes omit non-positive values with a warning; mixed time-zone offsets raise `ArgumentError`.
103
- - Invalid scales, colors, dimensions, bin definitions, and output extensions raise `ArgumentError`.
104
- - `to_svg` needs no optional gems. PNG methods raise `LoadError` with the missing gem's install command.
105
- - SVG text is escaped; color input accepts a hexadecimal value or a supported CSS color name.
106
- - PNG rendering uses a built-in 2× coverage pass before downsampling. Pure Ruby rendering is intended for charts and reports, not huge photo workloads.
81
+ - `to_svg` returns a standalone SVG string; `save` writes `.svg` or `.png` files. `to_png` returns PNG bytes and `to_image` returns a `Tessel::Image`.
82
+ - Paired x/y arrays must have the same length. Non-finite y values break line segments by default; use `gaps: :connect` to bridge them.
83
+ - Explicit axis limits must be ordered. Log scales omit non-positive values. Time axes reject mixed time zones while preserving local daylight-saving transitions.
84
+ - Invalid scales, colors, dimensions, and file extensions raise `ArgumentError`.
85
+ - Charts provide `_repr_svg_` for notebook frontends and `to_inlay` for [Inlay](https://github.com/rbgfx/inlay); neither is a runtime dependency.
107
86
 
108
87
  ## Development
109
88
 
110
89
  ```sh
111
90
  bundle install
112
91
  bundle exec rake verify
113
- bundle exec rbs validate
114
92
  ```
115
93
 
116
- The test suite compares all gallery PNGs against Lookalike snapshots. Update them intentionally with `bundle exec ruby examples/gallery.rb --update-snapshots`.
117
-
118
94
  ## License
119
95
 
120
- [MIT](LICENSE.txt)
96
+ MIT. See [LICENSE.txt](LICENSE.txt).
data/bench/inkplot.rb CHANGED
@@ -5,11 +5,20 @@ require "inkplot"
5
5
 
6
6
  points = 1_000.times.map { |index| Math.sin(index / 20.0) }
7
7
  line = Inkplot.line(points)
8
- scatter = Inkplot.scatter(10_000.times.map { |index| [index % 1_000, Math.sin(index / 100.0)] })
8
+ scatter = Inkplot.scatter(Array.new(10_000) { |index| index }, Array.new(10_000) { |index| (index * 7_919) % 10_000 })
9
9
 
10
10
  puts "YJIT=#{RubyVM::YJIT.enabled?} Ruby=#{RUBY_VERSION}"
11
11
  Benchmark.bm(22) do |bench|
12
12
  bench.report("1k line SVG") { line.to_svg }
13
- bench.report("1k line PNG") { line.to_png }
14
- bench.report("10k scatter PNG") { scatter.to_png }
13
+ end
14
+
15
+ begin
16
+ require "tessel"
17
+ require "glyphic"
18
+ Benchmark.bm(22) do |bench|
19
+ bench.report("1k line PNG") { line.to_png }
20
+ bench.report("10k scatter PNG") { scatter.to_png }
21
+ end
22
+ rescue LoadError => e
23
+ warn "PNG benchmarks skipped: #{e.message}"
15
24
  end
data/docs/index.html ADDED
@@ -0,0 +1,31 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="theme-color" content="#101113">
7
+ <meta name="description" content="Build clear SVG and PNG charts from plain Ruby data with Inkplot.">
8
+ <title>Inkplot — charts from Ruby</title>
9
+ <style>
10
+ :root{color-scheme:dark;--bg:#101113;--panel:#191b1f;--line:#2c2f34;--text:#f2f0e9;--muted:#a3a5aa;--accent:#c6f277;--mono:ui-monospace,SFMono-Regular,Menlo,monospace;--sans:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif}
11
+ *{box-sizing:border-box}body{margin:0;background:radial-gradient(ellipse at 72% -20%,#293523,transparent 42%),var(--bg);color:var(--text);font:16px/1.6 var(--sans)}a{color:inherit;text-decoration:none}a:hover{color:var(--accent)}.wrap{width:min(1080px,calc(100% - 40px));margin:auto}.nav{height:76px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line)}.brand{font-size:20px;font-weight:750;letter-spacing:-.04em}.brand span,.tag{color:var(--accent)}.navlinks{display:flex;gap:26px;color:var(--muted);font-size:14px}.hero{padding:94px 0 70px;max-width:800px}.tag{font:12px var(--mono);text-transform:uppercase;letter-spacing:.14em}h1{font-size:clamp(48px,8vw,88px);line-height:.98;letter-spacing:-.075em;margin:22px 0}.hero p{max-width:590px;color:var(--muted);font-size:19px}.actions{display:flex;gap:12px;margin-top:30px;flex-wrap:wrap}.button{padding:11px 17px;border:1px solid var(--line);border-radius:5px;font-weight:650}.primary{background:var(--accent);color:#14170e;border-color:var(--accent)}.install{margin-top:26px;display:inline-flex;gap:18px;background:#090a0b;border:1px solid var(--line);border-radius:6px;padding:12px 15px;font:14px var(--mono)}.install span{color:#72757b}.section{padding:46px 0 70px;border-top:1px solid var(--line)}.sectionhead{display:flex;justify-content:space-between;align-items:end;gap:24px;margin-bottom:24px}.section h2{font-size:28px;letter-spacing:-.045em;margin:8px 0}.sectionhead p{color:var(--muted);margin:0;max-width:420px}.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}.card{background:var(--panel);border:1px solid var(--line);border-radius:8px;overflow:hidden}.card img{display:block;width:100%;aspect-ratio:1.7;object-fit:cover;background:#11151b}.cardbody{padding:14px 16px}.card h3{font-size:15px;margin:0}.card p{font-size:13px;color:var(--muted);margin:4px 0 0}.features{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}.feature{border-left:1px solid var(--line);padding:3px 0 3px 16px}.feature p{margin:4px 0 0;color:var(--muted);font-size:14px}.code{padding:20px;background:#090a0b;border:1px solid var(--line);border-radius:8px;overflow:auto;font:14px/1.8 var(--mono);color:#d8e7c2}.foot{border-top:1px solid var(--line);padding:24px 0 38px;color:var(--muted);font-size:13px;display:flex;justify-content:space-between;gap:16px}
12
+ @media(max-width:700px){.hero{padding:68px 0 54px}.navlinks{gap:14px}.grid,.features{grid-template-columns:1fr}.sectionhead{align-items:start;flex-direction:column}.foot{flex-direction:column}}
13
+ </style>
14
+ </head>
15
+ <body><div class="wrap">
16
+ <nav class="nav" aria-label="Main navigation"><a class="brand" href="#top">ink<span>plot</span></a><div class="navlinks"><a href="#gallery">Gallery</a><a href="https://github.com/rbgfx/inkplot">GitHub</a><a href="https://rubygems.org/gems/inkplot">RubyGems</a></div></nav>
17
+ <main id="top">
18
+ <section class="hero"><div class="tag">A plotting toolkit for Ruby</div><h1>Make data<br>easy to see.</h1><p>Build clear SVG and PNG charts from plain Ruby data. A small, dependency-free core with thoughtful defaults and room to tune the details.</p><div class="actions"><a class="button primary" href="https://github.com/rbgfx/inkplot#quick-start">Read the quick start ↗</a><a class="button" href="https://github.com/rbgfx/inkplot/blob/main/examples/gallery/README.md">Browse all examples</a></div><div class="install"><span>$</span> gem install inkplot</div></section>
19
+ <section class="section" id="gallery"><div class="sectionhead"><div><div class="tag">Selected work</div><h2>Charts from a few lines of Ruby</h2></div><p>Line, bar, scatter, histogram, and area charts share one consistent API.</p></div><div class="grid">
20
+ <a class="card" href="https://github.com/rbgfx/inkplot/blob/main/examples/gallery/01-line.svg"><img src="https://raw.githubusercontent.com/rbgfx/inkplot/main/examples/gallery/01-line.svg" alt="Line chart example"><div class="cardbody"><h3>Readable trends</h3><p>Line charts with labeled axes and a restrained grid.</p></div></a>
21
+ <a class="card" href="https://github.com/rbgfx/inkplot/blob/main/examples/gallery/14-dark-theme.svg"><img src="https://raw.githubusercontent.com/rbgfx/inkplot/main/examples/gallery/14-dark-theme.svg" alt="Dark themed chart example"><div class="cardbody"><h3>Dark theme</h3><p>Charts that sit naturally in dark interfaces.</p></div></a>
22
+ <a class="card" href="https://github.com/rbgfx/inkplot/blob/main/examples/gallery/09-histogram.svg"><img src="https://raw.githubusercontent.com/rbgfx/inkplot/main/examples/gallery/09-histogram.svg" alt="Histogram example"><div class="cardbody"><h3>Distribution at a glance</h3><p>Explore a dataset with an automatic histogram.</p></div></a>
23
+ </div></section>
24
+ <section class="section"><div class="sectionhead"><div><div class="tag">Quick start</div><h2>From values to SVG</h2></div></div><pre class="code"><code>require "inkplot"
25
+
26
+ chart = Inkplot.line([3, 1, 4, 1, 5, 9], title: "A small series")
27
+ chart.save("series.svg")</code></pre></section>
28
+ <section class="section"><div class="features"><div class="feature"><strong>Plain Ruby data</strong><p>Arrays, hashes, CSV tables, and records with string or symbol keys.</p></div><div class="feature"><strong>SVG by default</strong><p>Standalone SVG from Ruby's standard library. Optional PNG rendering is pure Ruby.</p></div><div class="feature"><strong>Useful scales</strong><p>Linear, logarithmic, time, and ordered category axes, plus dark and light themes.</p></div></div></section>
29
+ </main><footer class="foot"><span>Inkplot · Charts from Ruby</span><span><a href="https://github.com/rbgfx/inkplot">Source</a> · MIT License</span></footer>
30
+ </div></body>
31
+ </html>
@@ -1 +1 @@
1
- <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="60" y="40" width="562" height="266"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 60 306 L 622 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="52" y="310" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><path class="grid-line" d="M 60 217.33 L 622 217.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="52" y="221.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><path class="grid-line" d="M 60 128.67 L 622 128.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="52" y="132.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="grid-line" d="M 106.83 40 L 106.83 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="106.83" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W1</text><path class="grid-line" d="M 200.5 40 L 200.5 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="200.5" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W2</text><path class="grid-line" d="M 294.17 40 L 294.17 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="294.17" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W3</text><path class="grid-line" d="M 387.83 40 L 387.83 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="387.83" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W4</text><path class="grid-line" d="M 481.5 40 L 481.5 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="481.5" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W5</text><path class="grid-line" d="M 575.17 40 L 575.17 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="575.17" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W6</text><path class="axis-line" d="M 60 40 L 60 306 L 622 306" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Weekly signups</text><text x="341" y="355" fill="#20242B" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Week</text><text x="14" y="180" fill="#20242B" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-90 14 180)">People</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 106.83 226.2 L 200.5 195.17 L 294.17 212.9 L 387.83 146.4 L 481.5 115.37 L 575.17 48.87" fill="none" stroke="#0072B2" stroke-width="2"/></g></g></svg>
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="60" y="40" width="562" height="266"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 60 306 L 622 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="52" y="310" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><path class="grid-line" d="M 60 217.33 L 622 217.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="52" y="221.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><path class="grid-line" d="M 60 128.67 L 622 128.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="52" y="132.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="grid-line" d="M 106.83 40 L 106.83 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="106.83" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W1</text><path class="grid-line" d="M 200.5 40 L 200.5 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="200.5" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W2</text><path class="grid-line" d="M 294.17 40 L 294.17 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="294.17" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W3</text><path class="grid-line" d="M 387.83 40 L 387.83 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="387.83" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W4</text><path class="grid-line" d="M 481.5 40 L 481.5 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="481.5" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W5</text><path class="grid-line" d="M 575.17 40 L 575.17 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="575.17" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W6</text><path class="axis-line" d="M 60 40 L 60 306 L 622 306" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Weekly signups</text><text x="341" y="355" fill="#20242B" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Week</text><text x="14" y="180" fill="#20242B" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-90 14 180)">People</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 106.83 226.2 L 200.5 195.17 L 294.17 212.9 L 387.83 146.4 L 481.5 115.37 L 575.17 48.87" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -1 +1 @@
1
- <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 297.4 L 622 297.4" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="301.4" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2.0</text><path class="grid-line" d="M 42 240.2 L 622 240.2" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="244.2" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4.0</text><path class="grid-line" d="M 42 183 L 622 183" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="187" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">3.0</text><path class="grid-line" d="M 42 125.8 L 622 125.8" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="129.8" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6.0</text><path class="grid-line" d="M 42 68.6 L 622 68.6" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="72.6" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">7.0</text><text x="42" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><text x="187" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><text x="332" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="477" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Missing values break a line</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 42 297.4 L 114.5 240.2" fill="none" stroke="#0072B2" stroke-width="2"/><path class="mark-line" d="M 259.5 183 L 332 125.8" fill="none" stroke="#0072B2" stroke-width="2"/><path class="mark-line" d="M 477 240.2 L 549.5 68.6" fill="none" stroke="#0072B2" stroke-width="2"/></g></g></svg>
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 297.4 L 622 297.4" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="301.4" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2.0</text><path class="grid-line" d="M 42 240.2 L 622 240.2" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="244.2" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4.0</text><path class="grid-line" d="M 42 183 L 622 183" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="187" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">3.0</text><path class="grid-line" d="M 42 125.8 L 622 125.8" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="129.8" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6.0</text><path class="grid-line" d="M 42 68.6 L 622 68.6" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="72.6" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">7.0</text><text x="42" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><text x="187" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><text x="332" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="477" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Missing values break a line</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 42 297.4 L 114.5 240.2" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/><path class="mark-line" d="M 259.5 183 L 332 125.8" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/><path class="mark-line" d="M 477 240.2 L 549.5 68.6" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -1 +1 @@
1
- <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="460" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 230.67 L 502 230.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="234.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">50</text><path class="grid-line" d="M 42 135.33 L 502 135.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="139.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">100</text><text x="195.33" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><text x="348.67" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="502" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><path class="axis-line" d="M 42 40 L 42 326 L 502 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Two latency percentiles</text><path class="mark-line" d="M 390 54 L 406 54" fill="none" stroke="#0072B2" stroke-width="2"/><text x="412" y="58" fill="#20242B" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">p50</text><path class="mark-line" d="M 390 72 L 406 72" fill="none" stroke="#E69F00" stroke-width="2"/><text x="412" y="76" fill="#20242B" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">p99</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 118.67 245.92 L 195.33 253.55 L 272 228.76 L 348.67 238.29 L 425.33 263.08 L 502 270.71" fill="none" stroke="#0072B2" stroke-width="2"/></g><g class="series series-1" data-series="1"><path class="mark-line" d="M 118.67 150.59 L 195.33 120.08 L 272 106.73 L 348.67 141.05 L 425.33 169.65 L 502 181.09" fill="none" stroke="#E69F00" stroke-width="2" stroke-dasharray="5 4"/></g></g></svg>
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="460" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 230.67 L 502 230.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="234.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">50</text><path class="grid-line" d="M 42 135.33 L 502 135.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="139.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">100</text><text x="195.33" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><text x="348.67" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="502" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><path class="axis-line" d="M 42 40 L 42 326 L 502 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Two latency percentiles</text><path class="mark-line" d="M 390 54 L 406 54" fill="none" stroke="#0072B2" stroke-width="2"/><text x="412" y="58" fill="#20242B" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">p50</text><path class="mark-line" d="M 390 72 L 406 72" fill="none" stroke="#E69F00" stroke-width="2"/><text x="412" y="76" fill="#20242B" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">p99</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 118.67 245.92 L 195.33 253.55 L 272 228.76 L 348.67 238.29 L 425.33 263.08 L 502 270.71" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g><g class="series series-1" data-series="1"><path class="mark-line" d="M 118.67 150.59 L 195.33 120.08 L 272 106.73 L 348.67 141.05 L 425.33 169.65 L 502 181.09" fill="none" stroke="#E69F00" stroke-width="2" stroke-dasharray="5 4" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="266"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 306 L 622 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="310" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><path class="grid-line" d="M 42 239.5 L 622 239.5" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="243.5" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><path class="grid-line" d="M 42 173 L 622 173" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="177" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><path class="grid-line" d="M 42 106.5 L 622 106.5" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="110.5" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><text x="187" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><text x="332" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">30</text><text x="477" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="axis-line" d="M 42 40 L 42 306 L 622 306" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Request latency</text><text x="332" y="355" fill="#20242B" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">ms</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><rect class="histogram-mark" x="71" y="73.25" width="108.75" height="232.75" fill="#0072B2"/><rect class="histogram-mark" x="179.75" y="173" width="108.75" height="133" fill="#0072B2"/><rect class="histogram-mark" x="288.5" y="272.75" width="108.75" height="33.25" fill="#0072B2"/><rect class="histogram-mark" x="397.25" y="239.5" width="108.75" height="66.5" fill="#0072B2"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="266"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 217.33 L 622 217.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="221.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="grid-line" d="M 42 128.67 L 622 128.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="132.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">60</text><text x="42" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2026-01</text><text x="144.46" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2026-03</text><text x="250.38" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2026-05</text><text x="356.31" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2026-07</text><text x="463.98" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2026-09</text><text x="569.9" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2026-11</text><path class="axis-line" d="M 42 40 L 42 306 L 622 306" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Monthly active users</text><text x="332" y="355" fill="#20242B" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Month</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 42 243.93 L 95.83 230.63 L 144.46 235.07 L 198.29 208.47 L 250.38 181.87 L 304.22 168.57 L 356.31 177.43 L 410.14 141.97 L 463.98 119.8 L 516.07 102.07 L 569.9 75.47 L 622 44.43" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 230.67 L 622 230.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="234.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="grid-line" d="M 42 135.33 L 622 135.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="139.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">50</text><path class="grid-line" d="M 114.5 40 L 114.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="114.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">v1.0</text><path class="grid-line" d="M 259.5 40 L 259.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="259.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">v1.1</text><path class="grid-line" d="M 404.5 40 L 404.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="404.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">v1.2</text><path class="grid-line" d="M 549.5 40 L 549.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="549.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">v1.3</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Release performance</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 114.5 287.87 L 259.5 211.6 L 404.5 240.2 L 549.5 87.67" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g><path class="rule-line" d="M 42 183 L 622 183" fill="none" stroke="#D55E00" stroke-width="1.5" stroke-dasharray="5 4"/><text x="618" y="179" fill="#D55E00" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Target</text><path class="rule-line" d="M 404.5 40 L 404.5 326" fill="none" stroke="#0072B2" stroke-width="1.5" stroke-dasharray="5 4"/><text x="408.5" y="52" fill="#0072B2" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Cache enabled</text><text x="549.5" y="87.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">peak</text></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="460" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#171B22"/><path class="grid-line" d="M 42 254.5 L 502 254.5" fill="none" stroke="#303744" stroke-width="1"/><text x="34" y="258.5" fill="#A9B2C0" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">10</text><path class="grid-line" d="M 42 183 L 502 183" fill="none" stroke="#303744" stroke-width="1"/><text x="34" y="187" fill="#A9B2C0" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">15</text><path class="grid-line" d="M 42 111.5 L 502 111.5" fill="none" stroke="#303744" stroke-width="1"/><text x="34" y="115.5" fill="#A9B2C0" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><path class="grid-line" d="M 88 40 L 88 326" fill="none" stroke="#303744" stroke-width="1"/><text x="88" y="344" fill="#A9B2C0" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Mon</text><path class="grid-line" d="M 180 40 L 180 326" fill="none" stroke="#303744" stroke-width="1"/><text x="180" y="344" fill="#A9B2C0" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Tue</text><path class="grid-line" d="M 272 40 L 272 326" fill="none" stroke="#303744" stroke-width="1"/><text x="272" y="344" fill="#A9B2C0" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Wed</text><path class="grid-line" d="M 364 40 L 364 326" fill="none" stroke="#303744" stroke-width="1"/><text x="364" y="344" fill="#A9B2C0" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Thu</text><path class="grid-line" d="M 456 40 L 456 326" fill="none" stroke="#303744" stroke-width="1"/><text x="456" y="344" fill="#A9B2C0" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Fri</text><path class="axis-line" d="M 42 40 L 42 326 L 502 326" fill="none" stroke="#A9B2C0" stroke-width="1"/><text x="320" y="22" fill="#E8ECF2" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Dark theme</text><path class="mark-line" d="M 390 54 L 406 54" fill="none" stroke="#0072B2" stroke-width="2"/><text x="412" y="58" fill="#E8ECF2" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Deploys</text><path class="mark-line" d="M 390 72 L 406 72" fill="none" stroke="#E69F00" stroke-width="2"/><text x="412" y="76" fill="#E8ECF2" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Rollbacks</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 88 225.9 L 180 168.7 L 272 197.3 L 364 82.9 L 456 125.8" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g><g class="series series-1" data-series="1"><path class="mark-line" d="M 88 283.1 L 180 268.8 L 272 211.6 L 364 225.9 L 456 140.1" fill="none" stroke="#E69F00" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="244"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 284 L 622 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="288" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><path class="grid-line" d="M 42 223 L 622 223" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="227" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">10</text><path class="grid-line" d="M 42 162 L 622 162" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="166" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><path class="grid-line" d="M 42 101 L 622 101" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="105" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">30</text><path class="grid-line" d="M 58.11 40 L 58.11 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="58.11" y="302" fill="#626B78" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-45 58.11 302)">Region 1 very long</text><path class="grid-line" d="M 187 40 L 187 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="187" y="302" fill="#626B78" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-45 187 302)">Region 5 very long</text><path class="grid-line" d="M 315.89 40 L 315.89 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="315.89" y="302" fill="#626B78" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-45 315.89 302)">Region 9 very long</text><path class="grid-line" d="M 444.78 40 L 444.78 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="444.78" y="302" fill="#626B78" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-45 444.78 302)">Region 13 very long</text><path class="grid-line" d="M 573.67 40 L 573.67 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="573.67" y="302" fill="#626B78" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-45 573.67 302)">Region 17 very long</text><path class="grid-line" d="M 605.89 40 L 605.89 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="605.89" y="302" fill="#626B78" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-45 605.89 302)">Region 18 very long</text><path class="axis-line" d="M 42 40 L 42 284 L 622 284" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Regional volume</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><rect class="bar-mark" x="44.99" y="216.9" width="25.24" height="67.1" fill="#0072B2"/><rect class="bar-mark" x="77.21" y="174.2" width="25.24" height="109.8" fill="#0072B2"/><rect class="bar-mark" x="109.44" y="131.5" width="25.24" height="152.5" fill="#0072B2"/><rect class="bar-mark" x="141.66" y="88.8" width="25.24" height="195.2" fill="#0072B2"/><rect class="bar-mark" x="173.88" y="235.2" width="25.24" height="48.8" fill="#0072B2"/><rect class="bar-mark" x="206.1" y="192.5" width="25.24" height="91.5" fill="#0072B2"/><rect class="bar-mark" x="238.32" y="149.8" width="25.24" height="134.2" fill="#0072B2"/><rect class="bar-mark" x="270.55" y="107.1" width="25.24" height="176.9" fill="#0072B2"/><rect class="bar-mark" x="302.77" y="253.5" width="25.24" height="30.5" fill="#0072B2"/><rect class="bar-mark" x="334.99" y="210.8" width="25.24" height="73.2" fill="#0072B2"/><rect class="bar-mark" x="367.21" y="168.1" width="25.24" height="115.9" fill="#0072B2"/><rect class="bar-mark" x="399.44" y="125.4" width="25.24" height="158.6" fill="#0072B2"/><rect class="bar-mark" x="431.66" y="82.7" width="25.24" height="201.3" fill="#0072B2"/><rect class="bar-mark" x="463.88" y="229.1" width="25.24" height="54.9" fill="#0072B2"/><rect class="bar-mark" x="496.1" y="186.4" width="25.24" height="97.6" fill="#0072B2"/><rect class="bar-mark" x="528.32" y="143.7" width="25.24" height="140.3" fill="#0072B2"/><rect class="bar-mark" x="560.55" y="101" width="25.24" height="183" fill="#0072B2"/><rect class="bar-mark" x="592.77" y="247.4" width="25.24" height="36.6" fill="#0072B2"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 326 L 622 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="330" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><path class="grid-line" d="M 42 230.67 L 622 230.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="234.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><path class="grid-line" d="M 42 135.33 L 622 135.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="139.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="42" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><text x="187" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">10</text><text x="332" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><text x="477" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">30</text><text x="622" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Custom latency ranges</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><rect class="histogram-mark" x="42" y="87.67" width="145" height="238.33" fill="#0072B2"/><rect class="histogram-mark" x="187" y="183" width="145" height="143" fill="#0072B2"/><rect class="histogram-mark" x="332" y="183" width="145" height="143" fill="#0072B2"/><rect class="histogram-mark" x="477" y="278.33" width="145" height="47.67" fill="#0072B2"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 305.57 L 622 305.57" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="309.57" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2.0</text><path class="grid-line" d="M 42 264.71 L 622 264.71" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="268.71" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">3.0</text><path class="grid-line" d="M 42 223.86 L 622 223.86" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="227.86" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">5.0</text><path class="grid-line" d="M 42 183 L 622 183" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="187" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6.0</text><path class="grid-line" d="M 42 142.14 L 622 142.14" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="146.14" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4.0</text><path class="grid-line" d="M 42 101.29 L 622 101.29" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="105.29" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">7.0</text><path class="grid-line" d="M 42 60.43 L 622 60.43" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="64.43" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">8.0</text><text x="42" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><text x="187" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><text x="332" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="477" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><text x="622" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">8</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Bridge short gaps</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 42 305.57 L 114.5 264.71 L 259.5 223.86 L 332 183 L 477 142.14 L 549.5 101.29 L 622 60.43" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 268.8 L 622 268.8" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="272.8" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">60</text><path class="grid-line" d="M 42 211.6 L 622 211.6" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="215.6" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">80</text><path class="grid-line" d="M 42 154.4 L 622 154.4" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="158.4" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">100</text><path class="grid-line" d="M 42 97.2 L 622 97.2" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="101.2" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">120</text><text x="42" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><text x="235.33" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><text x="428.67" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="622" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Rate limit changes</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 42 297.4 L 138.67 297.4 L 138.67 297.4 L 235.33 297.4 L 235.33 225.9 L 332 225.9 L 332 225.9 L 428.67 225.9 L 428.67 154.4 L 525.33 154.4 L 525.33 154.4 L 622 154.4 L 622 82.9" fill="none" stroke="#0072B2" stroke-width="2"/></g><path class="rule-line" d="M 42 154.4 L 622 154.4" fill="none" stroke="#626B78" stroke-width="1.5" stroke-dasharray="5 4"/><text x="618" y="150.4" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Current limit</text></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="460" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 326 L 502 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="330" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><path class="grid-line" d="M 42 254.5 L 502 254.5" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="258.5" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">10</text><path class="grid-line" d="M 42 183 L 502 183" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="187" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><path class="grid-line" d="M 42 111.5 L 502 111.5" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="115.5" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">30</text><path class="grid-line" d="M 99.5 40 L 99.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="99.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Q1</text><path class="grid-line" d="M 214.5 40 L 214.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="214.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Q2</text><path class="grid-line" d="M 329.5 40 L 329.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="329.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Q3</text><path class="grid-line" d="M 444.5 40 L 444.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="444.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Q4</text><path class="axis-line" d="M 42 40 L 42 326 L 502 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Quarterly sales</text><path class="mark-line" d="M 390 54 L 406 54" fill="none" stroke="#0072B2" stroke-width="2"/><text x="412" y="58" fill="#20242B" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Previous</text><path class="mark-line" d="M 390 72 L 406 72" fill="none" stroke="#E69F00" stroke-width="2"/><text x="412" y="76" fill="#20242B" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Current</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><rect class="bar-mark" x="52.35" y="211.6" width="93.3" height="114.4" fill="#0072B2"/><rect class="bar-mark" x="167.35" y="183" width="93.3" height="143" fill="#0072B2"/><rect class="bar-mark" x="282.35" y="197.3" width="93.3" height="128.7" fill="#0072B2"/><rect class="bar-mark" x="397.35" y="132.95" width="93.3" height="193.05" fill="#0072B2"/></g><g class="series series-1" data-series="1"><path class="mark-line" d="M 99.5 190.15 L 214.5 147.25 L 329.5 154.4 L 444.5 82.9" fill="none" stroke="#E69F00" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 326 L 622 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="330" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><path class="grid-line" d="M 42 254.5 L 622 254.5" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="258.5" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><path class="grid-line" d="M 42 183 L 622 183" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="187" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><path class="grid-line" d="M 42 111.5 L 622 111.5" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="115.5" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">8</text><path class="grid-line" d="M 42 40 L 622 40" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="44" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">10</text><text x="187" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><text x="332" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">30</text><text x="477" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Session length vs. pages</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><circle class="series-point" cx="71" cy="326" r="4" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/><circle class="series-point" cx="158" cy="290.25" r="4.71" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/><circle class="series-point" cx="201.5" cy="218.75" r="5.43" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/><circle class="series-point" cx="288.5" cy="254.5" r="4.71" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/><circle class="series-point" cx="361" cy="147.25" r="6.86" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/><circle class="series-point" cx="448" cy="111.5" r="7.57" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/><circle class="series-point" cx="535" cy="40" r="9" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/></g><text x="448" y="111.5" fill="#626B78" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">engaged</text></g></svg>
@@ -1,6 +1,6 @@
1
1
  # Inkplot gallery
2
2
 
3
- Generated by [`../gallery.rb`](../gallery.rb). Run `ruby examples/gallery.rb` from the repository root to refresh the SVG files.
3
+ Generated by [`../gallery.rb`](../gallery.rb). Run `ruby examples/gallery.rb` from the repository root to refresh the SVG previews.
4
4
 
5
5
  | Example | Preview | Example | Preview |
6
6
  |---|---|---|---|
@@ -8,9 +8,9 @@ Generated by [`../gallery.rb`](../gallery.rb). Run `ruby examples/gallery.rb` fr
8
8
  | Series | ![Multiple series](03-series.svg) | Scatter | ![Scatter plot](04-scatter.svg) |
9
9
  | Bars | ![Bars](05-bars.svg) | Horizontal bars | ![Horizontal bars](06-horizontal-bars.svg) |
10
10
  | Grouped bars | ![Grouped bars](07-grouped-bars.svg) | Stacked bars | ![Stacked bars](08-stacked-bars.svg) |
11
- | Signed stacks | ![Signed stacks](09-signed-stack.svg) | Area | ![Area chart](10-area.svg) |
12
- | Step | ![Step chart](11-step.svg) | Histogram | ![Histogram](12-histogram.svg) |
13
- | Log scale | ![Log scale](13-log-scale.svg) | Time scale | ![Time scale](14-time-axis.svg) |
14
- | Category order | ![Ordered categories](15-category-order.svg) | Dark theme | ![Dark chart](16-dark-theme.svg) |
15
- | Annotations | ![Chart annotations](17-annotations.svg) | Mixed marks | ![Mixed chart](18-combo.svg) |
16
- | Legend position | ![Legend placement](19-legend-position.svg) | Long labels | ![Rotated labels](20-long-categories.svg) |
11
+ | Histogram | ![Request latency histogram](09-histogram.svg) | Area | ![Area chart](10-area.svg) |
12
+ | Step | ![Step chart](11-step.svg) | Time scale | ![Time series](12-time.svg) |
13
+ | Annotations | ![Release annotations](13-annotations.svg) | Dark theme | ![Dark theme](14-dark-theme.svg) |
14
+ | Category labels | ![Dense categories](15-category-labels.svg) | Custom bins | ![Custom histogram bins](16-custom-bins.svg) |
15
+ | Connected gaps | ![Connected gaps](17-connected-gaps.svg) | Step series | ![Rate limit step chart](18-step-series.svg) |
16
+ | Combined marks | ![Bars and line](19-combined-marks.svg) | Scatter sizes | ![Scatter size mapping](20-scatter-sizes.svg) |