Skip to content

Block API: Support file: paths for block icons in block.json#79658

Open
mgiannopoulos24 wants to merge 8 commits into
WordPress:trunkfrom
mgiannopoulos24:add/file-path-icon-support
Open

Block API: Support file: paths for block icons in block.json#79658
mgiannopoulos24 wants to merge 8 commits into
WordPress:trunkfrom
mgiannopoulos24:add/file-path-icon-support

Conversation

@mgiannopoulos24

Copy link
Copy Markdown

What?

Support file: paths for block icons in block.json, allowing block authors to use "icon": "file:./assets/icon.svg" instead of being forced to set custom SVG icons via JavaScript only.

Also updates the JSON Schema to accept icon descriptor objects (src, background, foreground, shadowColor) in addition to the existing string form.

Why?

Currently, custom SVG icons can only be set via registerBlockType in JavaScript. The block.json icon field only accepts Dashicon slugs. This means block authors who want a custom SVG icon must either:

  1. Duplicate metadata between block.json and JS registration
  2. Register the block entirely in JS, losing the benefits of block.json (server-side registration, REST API exposure, etc.)

This PR closes that gap by bringing feature parity between block.json and JS-based icon registration, following the established file: prefix pattern already used by style, editorScript, render, and variations fields.

How?

Four layers of changes:

  • JSON Schema (schemas/json/block.json): Updated icon from { "type": "string" } to a oneOf accepting either a string or an object with src, background, foreground, shadowColor. Variation icon reuses via $ref.
  • PHP runtime (lib/blocks.php): New gutenberg_resolve_block_icon_path() hooked into block_type_metadata. When the icon starts with file:, it uses remove_block_asset_path_prefix() (the same utility used by scripts/styles/render) to resolve the path relative to block.json, reads the SVG file, and inlines the content. Handles both string and object forms.
  • Build system (packages/scripts/config/webpack.config.js): The CopyWebpackPlugin transform() now detects file: icons and inlines the SVG content at build time, so the built block.json is self-contained.
  • Icon rendering (packages/components/src/icon/index.tsx): The <Icon> component now detects SVG markup strings (starting with <svg or <?xml) and renders them directly with proper width/height from the size prop, rather than passing them through as Dashicon names.

Testing Instructions

1. Schema validation

node test/integration/validate-block-json-schema.js

All 126 block.json files should pass.

2. Unit tests

jest --config test/unit/jest.config.js packages/components/src/icon/test/index.tsx

All 13 tests should pass (10 existing + 3 new for SVG string rendering).

3. Manual test with a custom block

  1. Create a block with a custom SVG icon file (e.g., src/assets/icon.svg)
  2. Set "icon": "file:./assets/icon.svg" in block.json
  3. Build with npm run build (or npx wp-scripts build)
  4. Verify the icon appears in the block inserter

4. Object form test

{
    "icon": {
        "src": "file:./assets/icon.svg",
        "background": "#ff0000",
        "foreground": "#ffffff"
    }
}

Verify the icon renders with colored background in the inserter.

5. PHP-only registration (no build step)

For blocks not using @wordpress/scripts, verify the icon resolves correctly via server-side registration with register_block_type_from_metadata().

Use of AI Tools

This pull request was authored with the assistance of AI tooling (Deepseek via opencode). All AI-generated code has been reviewed and tested for correctness. See the WordPress AI Guidelines: https://make.wordpress.org/ai/handbook/ai-guidelines/.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: mgiannopoulos24 <mgiannopoulos24@git.wordpress.org>
Co-authored-by: ciampo <mciampini@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: [Package] Blocks, First-time Contributor.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: .

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions github-actions Bot added [Package] Components /packages/components First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository labels Jun 29, 2026
@github-actions

Copy link
Copy Markdown

👋 Thanks for your first Pull Request and for helping build the future of Gutenberg and WordPress, @mgiannopoulos24! In case you missed it, we'd love to have you join us in our Slack community.

If you want to learn more about WordPress development in general, check out the Core Handbook full of helpful information.

@mgiannopoulos24 mgiannopoulos24 marked this pull request as draft June 29, 2026 21:34
ciampo
ciampo previously requested changes Jun 30, 2026

@ciampo ciampo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think that supporting inline SVG code for the Icon is the right choice here, it's hacky and potentially insecure.

A better approach:

  • keep Icon unchanged,
  • resolve file:./icon.svg in the block metadata pipeline,
  • validate/sanitize the SVG,
  • pass a block-specific safe representation to BlockIcon.

The existing WP_Icons_Registry sanitization model is a much better precedent than dangerouslySetInnerHTML in @wordpress/components

@github-actions github-actions Bot added [Package] Blocks /packages/blocks and removed [Package] Components /packages/components labels Jun 30, 2026
@mgiannopoulos24 mgiannopoulos24 force-pushed the add/file-path-icon-support branch from f42c224 to f7e78dd Compare June 30, 2026 11:55
@mgiannopoulos24 mgiannopoulos24 requested a review from ciampo June 30, 2026 12:39
@ciampo ciampo dismissed their stale review June 30, 2026 15:17

The PR now doesn't dangerously parse an SVG string into the Icon component.

I will let other folks that are more experienced with the block API review the PR going forward.

@ciampo

ciampo commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

I dismissed my blocking review, and I'll let folks that are more experienced with the block API review this PR, once marked as ready for review.

@ciampo ciampo removed their request for review June 30, 2026 15:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository [Package] Blocks /packages/blocks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants