Skip to content

feat(highcharts): add Highcharts rendering backend - #140

Open
Sam (learningsam20) wants to merge 7 commits into
microsoft:devfrom
learningsam20:feat/highcharts-backend
Open

Sam (learningsam20) wants to merge 7 commits into
microsoft:devfrom
learningsam20:feat/highcharts-backend

Conversation

@learningsam20

@learningsam20 Sam (learningsam20) commented Oct 13, 2026 •

Copy link
Copy Markdown

Closes #141

What

Adds a highcharts backend to flint-js. The same Flint input compiles to a Highcharts option via assembleHighcharts(input) (also exported from the new flint-chart/highcharts subpath). validateChart accepts highcharts, and both the MCP server and the site editor render it. Follows docs/adding-a-backend.md; guide: docs/reference-highcharts.md.

Why

Flint already targets Vega-Lite, ECharts, Chart.js, Plotly, Excel, and Image-Charts. Highcharts is a widely deployed charting library with a mature, serializable option object, so it is a natural additional compile target for hosts that already ship Highcharts. This lets the same Flint semantic input drive a Highcharts render without a new authoring model.

Design / scope

  • Pure and offline. assembleHighcharts builds a plain option object; no network, no crypto, no new runtime dependencies. Highcharts stays a peer dependency and is externalized by the build, the same way the other backends treat their renderers.
  • Reuses the real pipeline. It runs the same Phase 0 semantic resolution and banded-axis overflow filtering as the other backends, then instantiates native Highcharts series.
  • Native series types and axes. Column/bar (column), line, area, pie/doughnut, scatter, histogram, radar (polar), heatmap, waterfall, and sunburst; datetime axes and per-panel faceting (_facet) are honoured.
  • Interactive. A Highcharts interactive renderer is registered, so interaction_spec presets mount: click-highlight dims by series (clicked series stays at full opacity, all others dim), plus the shared legend/navigation presets, using the same admission and warning reporting as the other backends.
  • Partial coverage by design. Templates without a faithful mapping are not emitted; the reference lists exactly what is ported.

Chart types (13)

Scatter, Bar, Grouped Bar, Stacked Bar, Histogram, Line, Area, Pie, Doughnut, Sunburst, Radar, Heatmap, Waterfall.

What changed

  • packages/flint-js/src/highcharts/**: assemble.ts, instantiate-spec.ts, colormap.ts, index.ts, interactive.ts, and templates/ (bar, line, scatter, pie, radar, histogram, heatmap, waterfall, sunburst, utils).
  • packages/flint-js: barrel + package.json exports (./highcharts) + optional peer dependency; tsup external; validate/index.ts registers the backend; interactive/ dispatch; test-data/highcharts-tests.ts; tests.
  • packages/flint-mcp: render/highcharts.ts (renders via the Highcharts CDN), render registry, tools/list.ts, tools/schemas.ts, bundled skill asset.
  • site: HighchartsView.tsx, InteractiveHighchartsView.tsx, supported-backends registry, docs catalog, editor.
  • docs: generated reference-highcharts.md plus README/DEVELOPMENT/overview/architecture/api-reference/adding-* and the agent skill; scripts/gen-chart-reference.ts extended.
  • CHANGELOG.md: added the Highcharts backend entry.

Verification

  • npm run typecheck — clean (flint-js + flint-mcp, including site types).
  • npm run lint — 0 errors (existing warnings only).
  • npm run test — 1679 passed (flint-js, including the 23 new tests/highcharts-backend.test.ts cases and new tests/smoke.test.ts assertions) and 86 passed (flint-mcp).
  • npm run site:build — passes; Highcharts renders in the site gallery and editor.

Acceptance checklist (docs/adding-a-backend.md §6)

  • Bar, line, area, and scatter templates render correctly on standard gallery matrices
  • tests/smoke.test.ts passes for the new assembler
  • npm run typecheck and npm run test pass at repo root
  • At least one dedicated test-data generator exercises backend-specific options (src/test-data/highcharts-tests.ts, registered in TEST_GENERATORS)

Semver

Minor. Adds a backend, a new subpath (flint-chart/highcharts), an MCP render target, and an optional peer dependency. No breaking changes.

Notes

  • Highcharts is pinned to 13.1.1 in site and flint-mcp, and the flint-js peer range is widened to ^11.0.0 || ^12.0.0 || ^13.0.0.
  • flint-mcp does not bundle Highcharts; the MCP renderer loads it from the Highcharts CDN (code.highcharts.com), so the package keeps its dependency footprint.
  • The site build sets NODE_OPTIONS=--max-old-space-size=8192 for vite build. Bundling the full site (now including Highcharts) exceeded Node's ~4 GB default heap during chunk rendering; CI's npm run site:build inherits the setting.

Add assembleHighcharts() as a fifth rendering backend alongside Vega-Lite,
ECharts, Chart.js, and Plotly. The backend reuses the shared core
pipeline (resolveChannelSemantics, computeLayout, filterOverflow) and
diverges only at Phase 2 template instantiation.

13 chart templates: Bar, Grouped Bar, Stacked Bar, Line, Area, Scatter,
Pie, Doughnut, Histogram, Radar, Heatmap, Waterfall, Sunburst.

- highcharts/ assembler, layout application, palette selection
- validateChart integration for the highcharts backend
- MCP render path via headless Chrome (puppeteer-core)
- Site HighchartsView + backend picker entry
- Test-data generators registered in TEST_GENERATORS
- Generated reference doc (docs/reference-highcharts.md)
- Docs: README, DEVELOPMENT, api-reference, adding-a-backend,
  adding-a-chart-template, test_plan, agent skill
@learningsam20

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

@Chenglong-MS

Copy link
Copy Markdown
Contributor

This is awesome!! Just in time for our 1.0 version release!

@Chenglong-MS

Copy link
Copy Markdown
Contributor

we have a bunch of updates on the dev (for the new release) so I'm thinking of doing this as 1.1 version release once the current version is out!

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved chart correctness, faceting, optional-dependency, interaction, site integration, and MCP rendering/security issues block approval.

38 open issues

And 18 more that still need to be addressed.

What changed in this PR

Introduces a Highcharts backend for Flint’s shared chart input, with library APIs, MCP rendering, and site previews.

Changes:

  • Adds 13 chart types, assembly APIs, validation, and interactive dispatch.
  • Integrates MCP exports and site previews with dependency/build updates.
  • Adds tests, fixtures, documentation, and community navigation.
File Description
site/​src/​shared/​theme.ts Adds community navigation constants.
site/​src/​shared/​supported-backends.ts Registers Highcharts as a preview backend.
site/​src/​shared/​docs-catalog.ts Registers Highcharts documentation.
site/​src/​routes/​Landing.tsx Adds WeChat content and scrolling.
site/​src/​routes/​Editor.tsx Adds Highcharts editor previews.
site/​src/​routes/​ChartWall.tsx Adds Highcharts output naming.
site/​src/​playground/​OverflowViewportLab.tsx Adjusts interactive backend selection.
site/​src/​i18n/​messages/​zh-CN.json Adds Chinese community labels.
site/​src/​i18n/​messages/​en.json Adds English community labels.
site/​src/​components/​SiteShell.tsx Adds community navigation links.
site/​src/​components/​InteractiveHighchartsView.tsx Mounts interactive Highcharts previews.
site/​src/​components/​HighchartsView.tsx Adds static and faceted previews.
site/​README.md Updates backend documentation.
site/​package.json Adds Highcharts and build-memory configuration.
scripts/​gen-chart-reference.ts Adds Highcharts reference generation.
README.md Documents Highcharts and community links.
packages/​flint-mcp/​tests/​server.test.ts Updates resource-count expectations.
packages/​flint-mcp/​src/​tools/​schemas.ts Accepts Highcharts requests.
packages/​flint-mcp/​src/​tools/​list.ts Lists Highcharts templates.
packages/​flint-mcp/​src/​render/​types.ts Extends render backend types.
packages/​flint-mcp/​src/​render/​index.ts Adds Highcharts render dispatch.
packages/​flint-mcp/​src/​render/​highcharts.ts Adds browser-based artifact rendering.
packages/​flint-mcp/​src/​cli.ts Updates supported-target help.
packages/​flint-mcp/​package.json Adds rendering dependencies.
packages/​flint-mcp/​assets/​flint-chart-author.SKILL.md Updates bundled authoring guidance.
packages/​flint-js/​tsup.config.ts Updates backend build configuration.
packages/​flint-js/​tests/​smoke.test.ts Adds public API assertions.
packages/​flint-js/​tests/​highcharts-backend.test.ts Adds backend assembly and validation tests.
packages/​flint-js/​src/​validate/​index.ts Registers Highcharts validation handling.
packages/​flint-js/​src/​test-data/​index.ts Registers Highcharts fixture generators.
packages/​flint-js/​src/​test-data/​highcharts-tests.ts Adds backend-specific gallery fixtures.
packages/​flint-js/​src/​interactive/​types.ts Extends interactive backend types.
packages/​flint-js/​src/​interactive/​index.ts Adds Highcharts renderer dispatch.
packages/​flint-js/​src/​index.ts Exports Highcharts APIs.
packages/​flint-js/​src/​highcharts/​templates/​waterfall.ts Adds waterfall mapping.
packages/​flint-js/​src/​highcharts/​templates/​utils.ts Adds shared template helpers.
packages/​flint-js/​src/​highcharts/​templates/​sunburst.ts Builds hierarchical sunburst series.
packages/​flint-js/​src/​highcharts/​templates/​scatter.ts Adds scatter and bubble mapping.
packages/​flint-js/​src/​highcharts/​templates/​radar.ts Adds polar radar mapping.
packages/​flint-js/​src/​highcharts/​templates/​pie.ts Adds pie and doughnut templates.
packages/​flint-js/​src/​highcharts/​templates/​line.ts Adds line and area templates.
packages/​flint-js/​src/​highcharts/​templates/​index.ts Registers Highcharts templates.
packages/​flint-js/​src/​highcharts/​templates/​histogram.ts Adds histogram binning and mapping.
packages/​flint-js/​src/​highcharts/​templates/​heatmap.ts Adds heatmap aggregation and mapping.
packages/​flint-js/​src/​highcharts/​templates/​bar.ts Adds bar-family templates.
packages/​flint-js/​src/​highcharts/​interactive.ts Adds the interactive renderer adapter.
packages/​flint-js/​src/​highcharts/​instantiate-spec.ts Applies layout, styling, and semantic decisions.
packages/​flint-js/​src/​highcharts/​index.ts Defines backend exports.
packages/​flint-js/​src/​highcharts/​colormap.ts Adds palette selection.
packages/​flint-js/​src/​highcharts/​assemble.ts Coordinates compilation and faceting.
packages/​flint-js/​package.json Adds the Highcharts subpath and optional peer.
package-lock.json Records dependency changes.
docs/​tutorials/​exploring-data.md Generalizes preview instructions.
docs/​test_plan.md Documents Highcharts fixtures.
docs/​reference-highcharts.md Adds the generated chart reference.
docs/​README.md Updates backend listings and counts.
docs/​overview.md Adds Highcharts overview references.
docs/​DEVELOPMENT.md Updates source-layout documentation.
docs/​architecture.md Updates backend architecture references.
docs/​api-reference.md Documents exports and validation support.
docs/​adding-a-chart-template.md Updates cross-backend guidance.
docs/​adding-a-backend.md Updates renderer integration guidance.
CHANGELOG.md Announces the Highcharts backend.
agent-skills/​flint-chart-author/​SKILL.md Updates Highcharts authoring guidance.

Review effort: Balanced

// ---------------------------------------------------------------------------

function applyFieldDisplayNames(option: any, names: Record<string, string> | undefined): void {
if (!names) return;
Comment on lines +268 to +272
const hasAxes = chartTemplate.channels.includes('x') || chartTemplate.channels.includes('y');

let hcOption: any;

if (hasFacet && hasAxes) {
const raw = values.map((r: any) => r[colField]).filter((v: any) => v != null && typeof v === 'number' && !isNaN(v));
colValues = [...new Set(raw)].map(String);
} else {
colValues = colField ? [...new Set(values.map((r: any) => String(r[colField])))] : [];
export { hcApplyLayoutToSpec, hcApplyTooltips } from './instantiate-spec';
export { hcTemplateDefs, hcAllTemplateDefs, hcGetTemplateDef, hcGetTemplateChannels } from './templates';
export { getPaletteForScheme, pickHighchartsPalette } from './colormap';
export { createHighchartsInteractiveRenderer } from './interactive';
Comment on lines +99 to +101
if (decision.zero && axisObj.min === undefined) {
axisObj.min = 0;
}
Comment on lines +114 to +115
case 'highcharts':
artifact = await renderHighcharts(spec, {
Comment on lines +85 to +96
useEffect(() => {
const chart = chartRef.current;
return () => {
try {
chart?.destroy();
} catch {
// A chart that failed to initialize can throw on destroy; unmount
// must still complete.
}
chartRef.current = null;
};
}, []);
Comment thread site/src/components/HighchartsView.tsx Outdated
Comment on lines +98 to +115
if (error) {
return (
<pre style={{ color: siteTheme.error, fontSize: 11, whiteSpace: 'pre-wrap', margin: 0 }}>
{error}
</pre>
);
}

return (
<div
ref={ref}
style={{
width: designedWidth != null ? designedWidth : '100%',
height: renderHeight,
maxWidth: constrain ? '100%' : undefined,
}}
/>
);
Comment on lines +38 to +48
try {
pending = sessionStorage.getItem(LANDING_SCROLL_TO_KEY);
if (pending) sessionStorage.removeItem(LANDING_SCROLL_TO_KEY);
} catch {
// Privacy modes may block storage.
}
if (pending !== WECHAT_SECTION_ID) return;
const timer = window.setTimeout(() => {
scrollToHeading(WECHAT_SECTION_ID);
}, 50);
return () => window.clearTimeout(timer);
Comment on lines +58 to +62
highcharts: {
id: 'highcharts',
label: 'Highcharts',
assemble: assembleHighcharts,
getTemplateDef: hcGetTemplateDef,

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +332 to +333
chartTemplate.instantiate(panelOption, panelContext);
hcApplyLayoutToSpec(panelOption, panelContext, []);
Comment on lines +381 to +383
if (input.chart_spec.title !== undefined) {
hcOption.title = { text: input.chart_spec.title };
}
Comment on lines +395 to +397
const capabilities: import('../core/interaction-spec').InteractionCapability[] = [];
if (hasLegend) capabilities.push('legend');
if (navAxes.length > 0) capabilities.push('navigation');
Comment on lines +56 to +57
const hasAxes = !!(option.xAxis || option.yAxis) && option.chart?.type !== 'pie';
if (hasAxes && !option._width) {
// Highcharts category axes handle zero via the numeric y/x axis; only
// pin soft zero bounds when the zero decision says to include zero and the axis
// is numeric (not category/datetime).
const isNumericAxis = !axisObj.type || axisObj.type === 'linear' || axisObj.type === 'value' || axisObj.type === 'datetime' || axisObj.type === 'logarithmic';
Comment on lines +95 to +96
if (colorField) {
const groups = groupBy(table, colorField);
legend: { layout: 'vertical', align: 'right', verticalAlign: 'middle' },
plotOptions: {
pie: {
allowPointSelect: true,
Comment on lines +52 to +54
const branchTotal = [...leafValues.entries()]
.filter(([key]) => key.startsWith(`${branch}·`))
.reduce((sum, [, v]) => sum + v, 0);
if (!opt || typeof opt !== 'object') return opt;
return {
...opt,
chart: { ...(opt.chart ?? {}), animation: false },
Comment on lines +58 to +62
highcharts: {
id: 'highcharts',
label: 'Highcharts',
assemble: assembleHighcharts,
getTemplateDef: hcGetTemplateDef,
@learningsam20

Copy link
Copy Markdown
Author

Chenglong Wang (@Chenglong-MS) I have fixed the copilot findings. Could you please review, merge?

we have a bunch of updates on the dev (for the new release) so I'm thinking of doing this as 1.1 version release once the current version is out!

@learningsam20

Sam (learningsam20) commented Oct 20, 2026 via email

Copy link
Copy Markdown
Author

@learningsam20

Copy link
Copy Markdown
Author

Chenglong Wang (@Chenglong-MS) could you merge this in dev?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a support for Highcharts rendering backend

3 participants