SuperAPI AI Directory

gm-data-chart

Data & analytics

View repository

Updated 10-16 09:44

About this skill

gmdiagram — GM Data Chart Skill

What This Skill Does

Generate publication-quality data visualization charts as standalone files. The output can be:

  • HTML: Single .html file with inline SVG and embedded CSS (default, no JavaScript)
  • SVG: Standalone .svg file
  • Mermaid: Text syntax (limited chart support, see Mermaid rules)
  • PNG/PDF: Via the export script at ../gm-architecture/skills/gm-architecture/scripts/export.sh

Output Directory Structure

All example files must be output to the correct directory structure:

assets/examples/
├── {example-name}.json      # JSON schema file
├── {example-name}.html      # HTML rendered output (same name as JSON)
└── images/                  # For preview screenshots only
    └── {example-name}-preview.png

Rules

Correct approach:

  • HTML and JSON files go in the examples/ root directory
  • Preview images go in the examples/images/ subdirectory
  • Filenames must be consistent (only extensions differ)

Prohibited approach:

  • Do NOT put HTML files in the images/ directory
  • Do NOT generate any non-image files in the images/ directory
  • Do NOT put JSON files in subdirectories (unless there's explicit categorization need)

Example

For the chrome-architecture example:

  • assets/examples/chrome-architecture.json
  • assets/examples/chrome-architecture.html
  • assets/examples/images/chrome-architecture-preview.png
  • assets/examples/images/chrome-architecture.html (WRONG: HTML should not be in images/)

Interactive Selection

When the user's request does NOT already specify all three choices (chart type, style, output format), use the AskUserQuestion tool to let the user choose.

Important: AskUserQuestion supports at most 4 options per question and 4 questions per call.

Selection Strategy

For each dimension, follow this logic:

  1. Can the choice be inferred from the user's description? → Skip asking, use the inferred value directly.
  2. Does the user explicitly state it? → Skip asking, use the stated value.
  3. Still ambiguous? → Ask via AskUserQuestion.

Question 1 — Chart Type (ask only if ambiguous)

The user's description usually makes the type obvious. Only ask when multiple types could fit. Since there are 9 chart types, split into groups:

First ask which group:

question: "Which chart category fits your needs?"
header: "Category"
options:
  - label: "Comparison"
    description: "Bar chart — compare categories with bars"
  - label: "Proportion"
    description: "Pie / Donut — show proportions of a whole"
  - label: "Trend / Distribution"
    description: "Line / Area / Scatter — show trends, area, or correlation"
  - label: "Special"
    description: "Radar / Funnel / Bubble / Table — multi-axis, pipeline, 3D data, or grid"

Then drill down within the category:

  • Comparison → Bar Chart (no further question needed)
  • Proportion → Ask: "Pie or Donut?" (2 options, simple)
  • Trend / Distribution → Ask: "Line / Area / Scatter?"
  • Special → Ask: "Radar / Funnel / Bubble / Table?"

Question 2 — Visual Style

Use the same 3-family approach as architecture-diagram:

First ask:
  "Which style family?" → Dark / Light+Clean / Creative

Then drill down within the family.

Infer from context when possible: technical content → dark, business → light-corporate, creative → cyberpunk/pastel.

Question 3 — Output Format

Default is HTML. Only ask if the user mentions a specific use case (GitHub → Mermaid, print → SVG/PDF).

Metadata Version Field

When generating JSON, metadata.version must follow these rules:

  • Format: Must conform to the SemVer (Semantic Versioning) format: major.minor.patch
  • Example: "0.6.1", "1.2.0", "2.0.0"
  • Forbidden placeholder versions: "0.0.0", "1.0", "1.0.0"

Recommended version strategy: It is recommended to use a value consistent with the plugin version, but this is not mandatory. What matters is maintaining format compliance.

JSON example:

"metadata": {
  "author": "gmdiagram",
  "date": "2026-04-14",
  "version": "0.6.1"
}

Validation rules:

  • Must contain 3 numeric segments separated by dots
  • Each segment must be pure digits
  • Leading zeros are not allowed (e.g. "01.02.03" is invalid)

Two-Step Generation Process

ALL chart generation follows exactly two steps. Never skip to output directly.

Step 1 — Extract to JSON Schema

Extract data from the user's natural language description into the typed JSON schema for the chosen chart type.

Schema files:

Chart Type Schema File
bar assets/schema-bar.json
pie assets/schema-pie.json
line assets/schema-line.json
area assets/schema-area.json
scatter assets/schema-scatter.json
radar assets/schema-radar.json
funnel assets/schema-funnel.json
bubble assets/schema-bubble.json
table assets/schema-table.json

Shared schema definitions are in assets/schema-shared.json (styleEnum, formatEnum, legendConfig, axisConfig, scatterAxisConfig, sanitizedString, etc.). Individual schemas reference shared definitions via $ref.

Critical: Nice Numbers algorithm runs in this step.

Read references/axis-and-grid.md for the full algorithm. Compute Y-axis ticks and store them in axis.y.ticks. For scatter and bubble charts, compute Nice Numbers for both X and Y axes and store in axis.x.ticks and axis.y.ticks. This avoids complex math in Step 2.

Data extraction rules:

  • Extract numeric values and labels from user text
  • Infer series names when multiple data sets are mentioned
  • When user provides percentages, store as raw values (not pre-multiplied)
  • When user says "compare X and Y", infer grouped bar chart with 2 series
  • All string fields have maxLength constraints — truncate if necessary with a note to the user
  • Scatter/Bubble: Extract x/y pairs from user data. Infer axis labels from context (e.g., "height vs weight" → x label "Height", y label "Weight"). For bubble, also extract size values.
  • Radar: Extract dimension labels (axes) and values per series. Ensure all series have the same number of data points as axes.
  • Funnel: Extract stage names and values. Note that values should be in descending order; if not, auto-sort will be applied during rendering.
  • Table: Extract column headers and row data. Ensure each row has a value for every column.

Validation:

  • Bar/Line/Area: series max 8, data per series max 30. If exceeded, must ask user to simplify.
  • Scatter: series max 8, data per series max 50.
  • Bubble: series max 5, data per series max 30.
  • Radar: axes min 3 max 12, series max 6, data length must match axes length.
  • Pie/Funnel: data max 12 (pie) / max 8 (funnel). If exceeded, suggest merging smallest items into "Others" (pie) or simplifying stages (funnel).
  • Table: columns min 2 max 12, rows max 50. Each row must contain all column keys.
  • All value fields must be finite numbers (no NaN, Infinity).
  • All color fields must match ^#[0-9a-fA-F]{6}$.
  • Radar axes[].maxValue: either all specified or all omitted (all-or-nothing). Partial specification is rejected in Step 1 validation.

Step 2 — Render Output

Read the corresponding render reference and template, then generate SVG wrapped in HTML.

Render references:

Chart Type Render Reference
bar references/render-bar.md
pie references/render-pie.md
line references/render-line.md
area references/render-area.md
scatter references/render-scatter.md
radar references/render-radar.md
funnel references/render-funnel.md
bubble references/render-bubble.md
table references/render-table.md

Shared references (read for all chart types):

  • references/axis-and-grid.md — axis, grid, tick rendering
  • references/color-palettes.md — palette selection and color assignment

Template: Use ../../assets/template-{style}.html (shared templates with chart CSS classes already added).

Rendering approach — Hybrid Mode:

  • Data marks (bars, arcs, lines, dots): pure SVG native elements (<rect>, <path>, <circle>, <line>)
  • Text (labels, legend, axis titles): foreignObject + CSS layout
  • All foreignObject root elements must include xmlns="http://www.w3.org/1999/xhtml"

HTML Language Attribute

Set the correct <html lang="..."> attribute according to the content language:

Content language lang attribute value Use case
English en Title, labels, and description are all in English
Simplified Chinese zh-CN Title, labels, and description contain Simplified Chinese
Traditional Chinese zh-TW Title, labels, and description contain Traditional Chinese
Japanese ja Title, labels, and description contain Japanese

Automatic detection rules

Use the following heuristic rules to determine the content language:

  1. Check the title field: If it contains Chinese characters (\u4e00-\u9fff), use zh-CN
  2. Check the subtitle field: If it contains Chinese characters, use zh-CN
  3. Check the main labels: If more than 50% of the labels contain Chinese, use zh-CN
  4. Default: If uncertain or mixed languages, use en

Example

Chinese content example:

<html lang="zh-CN">
<head><title>2025年各季度营收</title></head>

English content example:

<html lang="en">
<head><title>Q1-Q4 Revenue Comparison</title></head>

Importance

A correct lang attribute helps with:

  • Correct pronunciation by screen readers
  • Correct font rendering by browsers
  • SEO optimization

Chart Type Reference

Type Trigger Keywords Status
bar bar chart, column chart, bar chart, bar graph, comparison Available
pie pie chart, donut chart, pie chart, ring chart, share, proportion, proportion, percentage Available
line line chart, line graph, line chart, trend, trend, time series, time series Available
area area chart, area chart, stacked area, stacked area Available
scatter scatter chart, scatter plot, scatter plot, correlation, correlation, distribution Available
radar radar chart, spider chart, radar chart, spider chart, multi-dimensional, multi-dimensional Available
funnel funnel chart, funnel chart, conversion rate, conversion, pipeline, pipeline Available
bubble bubble chart, bubble chart, three-dimensional data, three-dimensional data Available
table data table, table chart, table, data table Available

Mermaid output matrix:

Type Mermaid Support Syntax
Bar Yes xychart-beta
Pie Yes pie title
Line Yes xychart-beta
Area No —
Scatter No —
Radar No —
Funnel No —
Bubble No —
Table No —

For chart types without Mermaid support, inform the user of the limitation and suggest HTML or SVG instead.

Data Extraction Rules

  • Extract numbers and labels directly from the user's description
  • Support formats like "Q1=1.2 million, Q2=1.5 million" or "Chrome 65%, Safari 19%"
  • Remove units from values (store "120" not "1.2 million"), put units in axis.y.label or subtitle
  • When multiple series are mentioned, create separate series objects
  • Handle percentage input: if all values sum to ~100, they're percentages; store as-is

File Naming Convention

Example file names must use kebab-case(lowercase letters connected by hyphens).

Naming format

{context}-{type}[-{variant}].{ext}
  • context: Scenario description (e.g. chrome, saas, ecommerce, quarterly-revenue)
  • type: Chart type (optional, e.g. architecture, flowchart, bar-chart)
  • variant: Variant identifier (optional, e.g. cyberpunk, minimalist, dark)
  • ext: file extension (json or html)

Correct and incorrect examples

Naming style Example Status
kebab-case ✅ chrome-architecture.json Correct
kebab-case ✅ quarterly-revenue.json Correct
kebab-case ✅ team-skills-radar.json Correct
camelCase ❌ chromeArchitecture.json Incorrect
PascalCase ❌ QuarterlyRevenue.json Incorrect
snake_case ❌ team_skills.json Incorrect
space ❌ chrome architecture.json Incorrect

Rules

  1. All lowercase: the file name contains no uppercase letters
  2. Word separation: use hyphens - to separate words, do not use underscores or spaces
  3. No special characters: use only letters, numbers and hyphens
  4. Clear semantics: the file name should clearly express the example content

Batch naming examples

For multiple style variants of the same system:

  • architecture-system.json (default style)
  • architecture-system-cyberpunk.json
  • architecture-system-minimalist.json
  • architecture-system-terminal.json

Quality Checklist

Before finalizing any chart output, verify ALL of the following:

Data & Schema

  • JSON validates against the chart type's schema file
  • axis.y.ticks uses nice numbers (no awkward decimals unless data has decimals)
  • For scatter/bubble: axis.x.ticks also uses nice numbers
  • All values are finite numbers (no NaN or Infinity)
  • Array sizes within limits (series, data, axes, columns, rows as per type constraints)

Visual

  • Bar width and spacing visually balanced
  • Text labels readable (>= 11px, contrast >= 3:1 against background)
  • ViewBox fits content — no clipping, no more than 20% whitespace
  • Legend matches actual data series/colors
  • Grid lines don't overlap with axis line

Technical

  • All foreignObject root elements have xmlns="http://www.w3.org/1999/xhtml"
  • All user text is HTML-entity-escaped (<, >, & in text content; additionally " and control chars in attribute values)
  • No user text in element name or attribute name positions
  • Colors in #rrggbb format only — no rgb(), rgba(), named colors, url()
  • No JavaScript in output
  • ViewBox width and height are integers (no decimals)
  • CSS classes match template definitions (.axis-line, .grid-line, .bar, .tick-label, etc.)

Security

  • No <script tags in output
  • No onerror, onload, onclick or other event handler attributes
  • No url() in inline style attributes
  • No <iframe>, <object>, <embed> tags
  • No extra <style> tags beyond what the template provides

Bar Chart Specific

  • Bars are proportional to data values
  • Y-axis ticks evenly spaced
  • X-axis labels centered under each bar/group
  • Negative values handled correctly (bars extend below baseline)

Pie Chart Specific

  • Slice angles are proportional to data values
  • Arcs start from 12 o'clock position (-90 degree offset)
  • Donut variant: inner arc path has correct annular sector (sweep-flag = 0 for inner arc)
  • Percentages computed and displayed correctly: (item.value / totalValue * 100).toFixed(1)
  • Slices < 5% have no external label (still shown in legend)

Line Chart Specific

  • Edge-to-edge X spacing used (NOT grouped slots like bar chart): pointX(g) = plotX + g * (plotWidth / (numDataPoints - 1))
  • Catmull-Rom smooth mode: phantom points computed correctly for boundary segments (P[-1] = 2*P[0] - P[1], P[n] = 2*P[n-1] - P[n-2])
  • Data point markers match the specified shape (circle, square, diamond, none)

Area Chart Specific

  • Stacked mode: cumulative values computed correctly, top-to-bottom render order
  • Overlaid mode: opacity applied correctly to each series fill
  • Nice Numbers applied to cumulative max (stacked) or individual max (overlaid)
  • Each area path closed to the baseline correctly

Scatter Chart Specific

  • Dual-axis Nice Numbers computed (both X and Y axes have ticks)
  • Both axes display tick labels
  • Triangle point shape rendered correctly (upright equilateral triangle)
  • Data point labels only shown when data[].label is present

Radar Chart Specific

  • Concentric polygon grid drawn (not circular grid)
  • axes[].maxValue is all-or-nothing: either all specified or all auto-computed
  • Polygon vertices computed correctly using polar coordinates from center
  • Data polygon normalized against per-axis maxValue
  • Axis labels positioned outside the outer polygon edge

Funnel Chart Specific

  • Data auto-sorted in descending order if not already sorted
  • Last stage has flat bottom (not tapered to a point)
  • Conversion rates displayed between adjacent stages (when showConversionRate: true)
  • Stage widths proportional to values relative to the maximum value

Bubble Chart Specific

  • Size mapped via area (r-squared), not linear radius: area = minR^2 + (size - minSize) / (maxSize - minSize) * (maxR^2 - minR^2)
  • Render order: ascending by size (small bubbles drawn first, large on top)
  • Dual numeric axes with Nice Numbers on both X and Y
  • Size legend included showing min/max bubble mapping

Table Chart Specific

  • No SVG graphic elements — pure foreignObject + HTML table
  • sanitizedString enforced on all cell content (no <> characters)
  • Highlight colors are fixed system values (Max: green, Min: red), not user-customizable
  • columns[].width matches pattern ^(\d{1,4}px|auto)$ — no arbitrary CSS values
  • Table width matches column widths appropriately

Iteration Workflow

Follow-up requests to modify an existing chart:

  1. Modify existing JSON — add/remove data points, change series
  2. Re-render from modified JSON
  3. Style change — re-render with different template (keep JSON unchanged)
  4. Format change — re-export to different output format

Common modifications:

  • "Add another series" → add to series array, re-render
  • "Change to horizontal" → set direction: "horizontal", re-render
  • "Stack the bars" → set variant: "stacked", re-render
  • "Switch to hand-drawn style" → change style, re-render with different template
  • "Convert pie to donut" → set variant: "donut", configure donut object, re-render
  • "Smooth the lines" → set smooth: true, re-render
  • "Show as stacked area" → set variant: "stacked" on area chart, re-render