Repository navigation
feat(highcharts): add Highcharts rendering backend - #140
Sam (learningsam20) wants to merge 7 commits into
Conversation
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
|
@microsoft-github-policy-service agree |
|
This is awesome!! Just in time for our 1.0 version release! |
|
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! |
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved chart correctness, faceting, optional-dependency, interaction, site integration, and MCP rendering/security issues block approval.
38 open issues
Field display names are not applied to facet panels · New Non-Cartesian faceting is bypassed · New Row-only facets render no panels · New Compiler imports fail without optional Highcharts peer · New Zero inclusion clips negative values · New Chart-spec titles are not forwarded to Highcharts · New Required Highcharts modules are not loaded · New Destroyed chart hosts accumulate on redraw · New Faceted interactive charts render as one empty chart · New Viewport offsets are used as local chart margins · New Horizontal colored bars swap Highcharts axes incorrectly · New Horizontal bars emit categories on the wrong axis · New Categorical stacked bars ignore percent stacking · New Horizontal stacked bars reverse native axes · New Numeric stacked bars ignore stackMode · New Horizontal grouped bars use incorrect axis mapping · New Local dodge layout is not applied · New Categorical series are not aligned to shared categories · New Area charts ignore monotone interpolation · New Pie and doughnut sorting has no effect · New
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; |
| 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'; |
| if (decision.zero && axisObj.min === undefined) { | ||
| axisObj.min = 0; | ||
| } |
| case 'highcharts': | ||
| artifact = await renderHighcharts(spec, { |
| 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; | ||
| }; | ||
| }, []); |
| 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, | ||
| }} | ||
| /> | ||
| ); |
| 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); |
| highcharts: { | ||
| id: 'highcharts', | ||
| label: 'Highcharts', | ||
| assemble: assembleHighcharts, | ||
| getTemplateDef: hcGetTemplateDef, |
There was a problem hiding this comment.
🟡 Changes recommended
Rendering correctness, interaction contract handling, and gallery registration have unresolved defects.
53 open issues
Use consistent category colors across facet panels · New Reserve title space in facet export dimensions · New Align capabilities with implemented interaction support · New Preserve dimensions for axis-free charts and facets · New Exclude categorical axes from numeric domain padding · New Apply continuous palettes to heatmap color axes · New Respect navigation axes and pan/zoom settings · New Honor admitted interaction behaviors and configured handlers · New Apply viewport intervals to native axes correctly · New Handle ordinal y-axis values in line and area charts · New Handle continuous color values by magnitude · New Enable pie and doughnut legend entries · New Aggregate sunburst values when no grouping or detail is bound · New Apply requested backgrounds to chart options · New Add Highcharts to the gallery catalog · New Highcharts backend is exposed without renderer branches StrictMode breaks pending home-page scroll Render failures prevent subsequent recovery Unmount cleanup destroys only the stale chart Facet metadata is stripped before rendering
And 33 more that still need to be addressed.
Review effort: Balanced
| chartTemplate.instantiate(panelOption, panelContext); | ||
| hcApplyLayoutToSpec(panelOption, panelContext, []); |
| if (input.chart_spec.title !== undefined) { | ||
| hcOption.title = { text: input.chart_spec.title }; | ||
| } |
| const capabilities: import('../core/interaction-spec').InteractionCapability[] = []; | ||
| if (hasLegend) capabilities.push('legend'); | ||
| if (navAxes.length > 0) capabilities.push('navigation'); |
| 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'; |
| if (colorField) { | ||
| const groups = groupBy(table, colorField); |
| legend: { layout: 'vertical', align: 'right', verticalAlign: 'middle' }, | ||
| plotOptions: { | ||
| pie: { | ||
| allowPointSelect: true, |
| 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 }, |
| highcharts: { | ||
| id: 'highcharts', | ||
| label: 'Highcharts', | ||
| assemble: assembleHighcharts, | ||
| getTemplateDef: hcGetTemplateDef, |
…ctions, and templates
|
Chenglong Wang (@Chenglong-MS) I have fixed the copilot findings. Could you please review, merge?
|
|
I have updated it based on the copilot findings as well as made it merge ready. Please review and merge. I thought 1.0 would be interesting since its major release with additional support, but based on the timelines if it suits 1.1 better, sure.From: Chenglong Wang ***@***.***>Date: Tuesday, 20 October 2026 at 4:19 AMTo: microsoft/flint-chart ***@***.***>Cc: Sam ***@***.***>; Mention ***@***.***>Subject: Re: [microsoft/flint-chart] feat(highcharts): add Highcharts rendering backend (PR #140)Chenglong-MS left a comment (microsoft/flint-chart#140)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!—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.
|
|
Chenglong Wang (@Chenglong-MS) could you merge this in dev? |

Closes #141
What
Adds a
highchartsbackend toflint-js. The same Flint input compiles to a HighchartsoptionviaassembleHighcharts(input)(also exported from the newflint-chart/highchartssubpath).validateChartacceptshighcharts, and both the MCP server and the site editor render it. Followsdocs/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
optionobject, 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
assembleHighchartsbuilds a plainoptionobject; 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.column), line, area, pie/doughnut, scatter, histogram, radar (polar), heatmap, waterfall, and sunburst; datetime axes and per-panel faceting (_facet) are honoured.interaction_specpresets mount:click-highlightdims 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.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, andtemplates/(bar, line, scatter, pie, radar, histogram, heatmap, waterfall, sunburst, utils).packages/flint-js: barrel +package.jsonexports(./highcharts) + optional peer dependency;tsupexternal;validate/index.tsregisters 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: generatedreference-highcharts.mdplus README/DEVELOPMENT/overview/architecture/api-reference/adding-* and the agent skill;scripts/gen-chart-reference.tsextended.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 newtests/highcharts-backend.test.tscases and newtests/smoke.test.tsassertions) 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)tests/smoke.test.tspasses for the new assemblernpm run typecheckandnpm run testpass at repo rootsrc/test-data/highcharts-tests.ts, registered inTEST_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
13.1.1insiteandflint-mcp, and theflint-jspeer range is widened to^11.0.0 || ^12.0.0 || ^13.0.0.flint-mcpdoes not bundle Highcharts; the MCP renderer loads it from the Highcharts CDN (code.highcharts.com), so the package keeps its dependency footprint.NODE_OPTIONS=--max-old-space-size=8192forvite build. Bundling the full site (now including Highcharts) exceeded Node's ~4 GB default heap during chunk rendering; CI'snpm run site:buildinherits the setting.