
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Chart.js plugin that generates natural language descriptions of chart data for screen readers
Chart.js plugin for generating natural language descriptions of chart data
A Chart.js plugin that generates natural language descriptions for screen readers and assistive technologies.
npm install chart2text
import Chart from 'chart.js/auto';
import { chart2text } from 'chart2text';
Chart.register(chart2text);
const ctx = document.getElementById('myChart');
new Chart(ctx, {
type: 'line',
data: {
labels: ['2020', '2021', '2022', '2023'],
datasets: [{
label: 'Revenue',
data: [50000, 65000, 72000, 85000]
}]
},
options: {
plugins: {
chart2text: {
enabled: true,
xUnit: 'year',
yUnit: 'dollars',
yAxisCurrency: 'USD'
}
}
}
});
Generated description:
"This chart shows Revenue based on year. Starting at $50,000 when year is 2020, it rises at a rate of about $11,667 per year, reaching $85,000 by year 2023."
new Chart(ctx, {
type: 'line',
data: {
labels: [55, 60, 65, 70],
datasets: [{
label: 'Retirement Income',
data: [2500, 3200, 4000, 4500]
}]
},
options: {
plugins: {
chart2text: {
datasetLabel: 'Monthly Retirement Income',
xUnit: 'age',
yUnit: 'dollars',
yAxisCurrency: 'USD',
useRounding: true
}
}
}
});
new Chart(ctx, {
type: 'bar',
data: {
labels: ['Q1', 'Q2', 'Q3', 'Q4'],
datasets: [{
label: 'Sales by Quarter',
data: [45000, 52000, 48000, 61000]
}]
},
options: {
plugins: {
chart2text: {
datasetLabel: 'Quarterly Sales',
yAxisCurrency: 'USD'
}
}
}
});
Generated description:
"This bar chart shows Quarterly Sales. There are 4 categories. Values range from $45,000 to $61,000. The highest value is Q4 at $61,000. The lowest value is Q1 at $45,000."
For sequential data (time series, ages), use descriptor: 'trend':
new Chart(ctx, {
type: 'bar',
data: {
labels: [55, 60, 65, 70, 75],
datasets: [{
label: 'Retirement Balance',
data: [150000, 225000, 320000, 385000, 420000]
}]
},
options: {
plugins: {
chart2text: {
descriptor: 'trend',
datasetLabel: 'Retirement Balance',
xUnit: 'age',
yUnit: 'dollars',
yAxisCurrency: 'USD'
}
}
}
});
new Chart(ctx, {
type: 'line',
data: { /* ... */ },
options: {
plugins: {
chart2text: {
templates: {
introduction: 'The data shows {datasetLabel} over {xUnit}.',
firstSegment: {
increasing: 'Beginning at {startY}, it increases to {endY}.',
decreasing: 'Beginning at {startY}, it decreases to {endY}.',
flat: 'It stays constant at {startY}.'
}
}
}
}
}
});
| Option | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable/disable the plugin |
descriptor | 'auto' | 'trend' | 'categorical' | 'auto' | Description strategy |
multiDatasetIntroduction | boolean | true | List all datasets before describing each |
sortPieSlices | boolean | true | Sort pie slices largest to smallest |
combineStacks | boolean | false | Combine stacked datasets into totals |
locale | string | 'en' | Locale for number formatting |
datasetLabel | string | 'data' | Label for the dataset |
xUnit | string | 'units' | Unit name for x-axis |
yUnit | string | 'units' | Unit name for y-axis |
xAxisCurrency | string | undefined | Currency code for x-axis |
yAxisCurrency | string | undefined | Currency code for y-axis |
useRounding | boolean | true | Use natural rounding for readability |
precision | number | 2 | Decimal places when rounding disabled |
variationStrategy | 'random' | 'sequential' | 'random' | Template variation selection |
templates | TemplateSet | Built-in | Custom template overrides |
The descriptor option controls analysis strategy:
'auto' (default):
'trend': Use piecewise regression
'categorical': Describe min/max and list values
For stacked bar/area charts, use combineStacks: true to describe totals instead of individual datasets:
new Chart(ctx, {
type: 'bar',
data: {
labels: ['Q1', 'Q2', 'Q3', 'Q4'],
datasets: [
{ label: 'Product A', data: [30, 40, 35, 50] },
{ label: 'Product B', data: [20, 25, 30, 35] }
]
},
options: {
scales: {
x: { stacked: true },
y: { stacked: true }
},
plugins: {
chart2text: {
combineStacks: true,
datasetLabel: 'Total Quarterly Revenue'
}
}
}
});
All text is generated from templates. No English is hardcoded in the logic.
Trend Analysis (line charts):
introduction - Chart introductionfirstSegment - First trend segmentsubsequentSegment - Middle segmentsdisconnectedSegment - Segments with data gapsfinalSegment - Final segmentCategorical (bar/pie charts):
chartIntroduction - Chart type and datasetcategoryCount - Number of categoriesvalueRange - Min/max rangehighestValue, lowestValue - Extreme valuesallValues, topValues, notableValues - Value listsMulti-Dataset:
introduction - Lists all datasetsGeneral:
seriesLabel - Default label for unnamed datasetsTrend templates: {datasetLabel}, {xUnit}, {yUnit}, {startX}, {endX}, {startY}, {endY}, {changeRate}
Categorical templates: {chartType}, {datasetLabel}, {count}, {minValue}, {maxValue}, {label}, {value}, {values}
Multi-dataset templates: {count}, {datasets}
Follows WCAG 2.1 Level AA:
aria-describedby, aria-label, role="img"<div> with full description.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
Trend Analysis (line charts, optional for bar charts):
segreg libraryCategorical (bar/pie charts):
See live demo or /demo directory for:
Pull requests welcome.
MIT © Charles McNulty
FAQs
Chart.js plugin that generates natural language descriptions of chart data for screen readers
We found that chart2text demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.