Guide

Chart Builder 3.7.0 — Release Notes

Release: Chart Builder 3.7.0 · PRC Platform 1.5 Work period: April 2026 Scope: prc-chart-builder


Overview

Chart Builder 3.7.0 ships the PRC Chart Handoff (PCH) import pipeline — a one-way bridge from pewplots (R) to Chart Builder (WordPress). Researchers can now export a .pch.json file from pewplots and hand it to a web producer, who uploads it in the Chart Builder admin to create a fully configured draft chart post: data pre-loaded, chart type set, axes and legend configured, and all type-specific styling defaults applied.

The release also fixes a long-standing editor issue where v2 blocks were incorrectly flagged as needing the v1 → v2 migration every time the editor opened.


What's New

1. PCH Import Pipeline

Background

pewplots is the internal R package used by Data Labs researchers to produce Pew Research charts. Until now, moving a chart from pewplots to Chart Builder required manually re-entering data, selecting the right chart type, and reapplying styling — a tedious, error-prone process.

PCH (PRC Chart Handoff) is a lightweight JSON format that captures everything about a chart in a tool-agnostic way: the data in tidy/long format, the chart type and orientation, metadata (title, subtitle, note, source), and optional styling config (colors, axis labels, legend, labels, type-specific options). A single export_to_pch() call in pewplots produces the file; a single upload in Chart Builder consumes it.

This is a one-way pipeline. PCH → Chart Builder only. There is no export from Chart Builder back to PCH.

REST endpoint

Route: POST /prc-chart-builder/v1/import-pch

The endpoint accepts a complete .pch.json object, validates the schema, converts it to Chart Builder block attributes, creates a draft chart post, and returns:

{
  "post_id": 12345,
  "edit_url": "https://example.com/wp-admin/post.php?post=12345&action=edit",
  "warnings": []
}

Requires edit_posts capability. See includes/chart-handoff/class-pch-import-endpoint.php.

Tidy-to-wide data pivot

PCH uses R-native tidy/long format (one observation per row):

"values": [
  { "country": "Germany", "share": 40, "opinion": "Favorable" },
  { "country": "Spain",   "share": 50, "opinion": "Favorable" },
  { "country": "Germany", "share": 20, "opinion": "Unfavorable" },
  { "country": "Spain",   "share": 30, "opinion": "Unfavorable" }
]

Chart Builder's table block and charting library expect wide format (one row per x-value):

[
  { "x": "Germany", "Favorable": 40, "Unfavorable": 20 },
  { "x": "Spain",   "Favorable": 50, "Unfavorable": 30 }
]

The pivot is performed at import time by pivot_pch_data_to_wide(). The independent variable column is always keyed 'x' in the pivoted data — matching the convention enforced by the Chart Builder editor's table parser, which hardcodes the first column key as 'x' regardless of the original column name.

Key attribute values set by the importer:

AttributeValueWhy
io.chartData[n].xIndependent variable valueFirst column always 'x'
dataRender.x'x'Editor table parser convention
io.independentVariable'x'Display label in editor UI
dataRender.yOriginal y-column name (e.g. 'share')Non-first columns keep original names
dataRender.categoriesUnique category valuesDerived from categoryColumn

Chart type mapping

PCH describes orientation separately from chart type. Chart Builder uses distinct slugs for horizontal vs vertical variants. The importer maps them:

PCH chartTypePCH orientationCB layout.type
barhorizontal (default)bar
barverticalcolumn
stacked-barhorizontalstacked-bar
stacked-barverticalstacked-column
diverging-barhorizontaldiverging-bar
lineline
areaarea
dot-plotdot-plot
scatterscatter

3-layer attribute merge

The importer uses the same 3-layer merge strategy as the AI generation endpoint (trait-chart-block-defaults.php):

Layer 1: block.json defaults
    ↓  deep_merge
Layer 2: variation template defaults (chart-type-specific)
    ↓  deep_merge
Layer 3: PCH overrides (only what PCH actually specifies)

The variation templates (in .shared/variation-templates/) define opinionated chart-type defaults — for example, bar charts default to sortOrder: 'descending' and specific tickLabels styles. The PCH override layer only writes attributes that PCH explicitly provides, so if PCH has no axis config, the variation template's axis settings survive untouched.

PCH JSON Schema

The authoritative schema is includes/chart-handoff/src/schema.json (ID: prc-chart-handoff/v1). It covers all required and optional fields, supported chartType values, data sub-fields, and config properties.

JS converter and unit tests

includes/chart-handoff/src/pch-to-chart-builder.js is a standalone JS implementation of the same conversion logic. It is used by the Jest unit tests (tests/integration/chart-handoff/pch-to-chart-builder.test.js) to validate the conversion without a running WordPress instance. Test fixtures in tests/fixtures/chart-handoff/ cover bar, column, stacked bar, diverging bar, line, area, dot-plot, and scatter chart types.

All 41 unit tests pass.

Technical reference

Full documentation — schema reference, file locations, data flow details, chart type mapping table, REST endpoint spec, fixture file index, lossy conversion notes, and a guide for adding new chart types — is at includes/chart-handoff/README.md.

pewplots side

For the R implementation (how to call export_to_pch(), add per-function PCH metadata, and handle lossy features), see PCH-HANDOFF.md in the pewplots repository.


2. v1 Block Validation Fix

Problem: When a v2 Chart Builder block was opened in the editor, the deprecations/v1.js deprecation handler's isEligible function would return true for any block lacking an explicit _version attribute — which included many valid v2 blocks. This caused unnecessary "block recovery" prompts and potential re-migration of already-current blocks.

Fix: isEligible now short-circuits immediately if attributes._version === 'v2':

// deprecations/v1.js
isEligible( attributes ) {
    if ( attributes._version === 'v2' ) {
        return false;
    }
    // ... existing eligibility checks
}

This prevents any v2 block from being offered the v1 migration, regardless of which other attributes are present.


Files Changed

FileChange
includes/chart-handoff/class-pch-import-endpoint.phpNew — REST endpoint and PHP converter
includes/chart-handoff/src/pch-to-chart-builder.jsNew — JS converter
includes/chart-handoff/src/schema.jsonNew — PCH JSON Schema v1
includes/chart-handoff/README.mdNew — PCH technical reference
tests/integration/chart-handoff/pch-to-chart-builder.test.jsNew — unit tests (41 tests)
tests/fixtures/chart-handoff/*.pch.jsonNew — test fixtures (9 files)
src/chart/deprecations/v1.jsFixed isEligible short-circuit for v2 blocks
src/chart/block.jsonRemoved pchSourceColumns and pchDataLayout (roundtrip fields, never shipped)

Upgrade Notes

No database migrations. No breaking changes. The new REST endpoint registers automatically on plugin load and is immediately available to authenticated users with edit_posts.

To test the import locally:

  1. Generate a .pch.json from pewplots using export_to_pch().
  2. In the Chart Builder admin, click "Import from pewplots" and upload the file.
  3. Review the created draft chart post and publish.

Was this helpful?