lini 0.22.0

Pretty diagrams, charts, and technical drawings from plain text, with fine-grained control. Compiles to clean, themeable SVG.
Documentation
// The chart family on one dashboard [SPEC 14]: grouped / stacked / horizontal
// bars, line curves (linear, smooth, step) with markers and per-point labels,
// stacked areas, a scatter, bubbles sized by a third value, and the pie pair.
{
  layout: grid; columns: repeat(2); gap: 24;
}

|chart| "Signups" { categories: "Jan", "Feb", "Mar", "Apr", "May"; } [
  |area| "free" { data: 30, 45, 60, 55, 80; }
  |area| "paid" { data: 10, 18, 22, 30, 38; }
]

|chart| "Revenue by region ($k)" {
  categories: "Q1", "Q2", "Q3", "Q4"; bars: stacked;
} [
  |bars| "NA" { data: 40, 45, 50, 60; }
  |bars| "EU" { data: 30, 35, 33, 40; }
  |bars| "APAC" { data: 20, 25, 30, 38; }
]

|chart| "Deploy time (s)" { categories: "build", "test", "ship"; } [
  |bars| "v1" { data: 96, 154, 41; }
  |bars| "v2" { data: 63, 117, 38; }
]

|chart| "Quarterly hires by team" {
  direction: row; categories: "Engineering", "Sales", "Support", "Ops";
} [
  |axis#people| "people" { side: bottom; }
  |bars| "Q1" { data: 12, 8, 5, 3; }
  |bars| "Q2" { data: 15, 10, 6, 4; }
  |band| "surge" { span: 10 15; axis: people; fill: --amber; }
  |mark| "target 10" {
    at: 10; axis: people; stroke: --rose-deep; stroke-style: dashed;
  }
]

|chart| "Latency (ms)" { categories: "p50", "p90", "p99", "p999"; } [
  |line| "v1" {
    data: 15, 70, 150, 480; marker: circle; labels: "Low", "Medium", "High", "Max";
  }
  |line| "v2" { data: 12, 40, 100, 300; stroke-style: dashed; marker: circle; }
  |line| "goal" { data: 10, 30, 60, 150; stroke-style: dotted; }
]

|chart| "Active users (k)" {
  categories: "6h", "9h", "12h", "15h", "18h", "21h";
} [
  |line| "web" { data: 8, 12, 19, 22, 17, 11; curve: smooth; marker: dot; }
]

|chart| "Tier price ($)" { categories: "0", "10", "20", "30"; } [
  |line| { data: 5, 5, 12, 12; curve: step; }
]

|chart| "Markets — scatter" [
  |axis| "growth %" { side: bottom; }
  |axis| "share %" { side: left; }
  |dots| { data: 12 40, 25 55, 38 30, 8 22, 30 12; }
]

|chart| "Markets — bubbles" [
  |axis| "growth %" { side: bottom; }
  |axis| "share %" { side: left; }
  |bubble| "EU" { at: 12 40; value: 8; fill: --teal; }
  |bubble| "US" { at: 25 55; value: 20; fill: --rose; }
  |bubble| "APAC" { at: 38 30; value: 14; fill: --sky; }
  |bubble| "LatAm" { at: 30 15; value: 6; fill: --amber; }
]

|pie| "Traffic sources" [
  |slice| "Search" { value: 45; }
  |slice| "Direct" { value: 25; }
  |slice| "Social" { value: 18; }
  |slice| "Referral" { value: 12; }
]

|pie| "Spend" { hole: 0.5; } [
  |slice| "Ads" { value: 40; }
  |slice| "SEO" { value: 30; }
  |slice| "Direct" { value: 30; }
]