Download the PHP package cloakwp/block-parser without Composer
On this page you can find all versions of the php package cloakwp/block-parser. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download cloakwp/block-parser
More information about cloakwp/block-parser
Files in cloakwp/block-parser
Package block-parser
Short Description Parse Gutenberg + ACF Blocks into structured objects.
License LGPL-3.0-only
Informations about the package block-parser
CloakWP Block Parser
CloakWP Block Parser is a PHP library designed to parse and transform Gutenberg and ACF blocks into structured objects/JSON. This package is part of the CloakWP ecosystem, but can be used independently or as a dependency of your own plugins/themes/packages.
Features
- Parse Gutenberg (core) blocks into objects/JSON
- Parse Advanced Custom Fields (ACF) blocks into objects/JSON
- Extensible architecture for custom block transformers
- Filters for modifying parsed block data
Motivation
WordPress block content is stored as HTML strings in the database rather than as structured data (e.g. JSON). This is particularly a problem for decoupled/headless projects where you may wish to render things your own way; to do so, you need the blocks in JSON/structured object form -- turns out this is surprisingly difficult to achieve. CloakWP Block Parser simplifies this process by providing a clean and organized way to parse and transform blocks content into structured data.
Installation
You can install this package via Composer:
Requires PHP 8.4+ with the DOM extension. HTML extraction uses PHP's
native Dom\HTMLDocument HTML5 parser and CSS selectors. WordPress's
parse_blocks() continues to parse block delimiters and nesting.
Example Output
Structured data
Usage
Basic Usage
HTML adapters
The default NativeHtmlAdapter parses UTF-8 HTML once per block, only when an
attribute needs HTML. Nested query sources reuse node contexts. Stored values,
defaults, and post meta do not create a DOM.
Inject an implementation of HtmlAdapterInterface to select an engine for one
parser, including its nested blocks and synced patterns:
pQuery is optional in production. Install tburry/pquery:^1.1 explicitly to use
PQueryHtmlAdapter; it is already included in development dependencies for
tests and comparisons. The same adapter can be passed to
new AttributeParser($adapter) for standalone extraction.
For parser instances created by integrations, choose the default through a filter:
Explicit constructor injection takes precedence over the filter. The filter
also applies to standalone AttributeParser instances and must return an
HtmlAdapterInterface. BlockParser::getHtmlAdapter() exposes the chosen adapter
to custom transformers.
An adapter implements parse(string): HtmlNodeInterface. Nodes provide
select(), selectAll(), attribute(), html(), text(), and tagName().
Selections return elements in document order and include the current element
when it matches, so fields inside query sources can read the query row itself.
Omitting a selector reads the first element. Missing matches/attributes return
null, while empty values are omitted by AttributeParser.
Both adapters support attribute, html, rich-text, text, tag, and nested
query sources. Table cells retain their context, including th tags and rich
text without selectors. Nested meta sources retain the post ID, and omitted
query rows produce dense JSON arrays.
Native HTML5 recovery and serialization can differ from pQuery on malformed
markup, entity escaping, whitespace, and advanced selectors. Native markup
preserves entity escaping and text() preserves text-node whitespace; pQuery
retains its legacy serialization and whitespace behavior. Review payload changes
when switching an existing installation. Invalid native CSS selectors throw
DOMException rather than silently producing missing attributes.
Extending
Custom Transformers
The BlockParser uses the built-in core function, `parse_blocks()`, to initially parse the blocks, but unfortunately this function doesn't do the full job. So, we extend the basic built-in parsing with block "transformers". By default, the BlockParser uses the following transformers: - CoreBlockTransformer (for Gutenberg core blocks) - ACFBlockTransformer (for ACF blocks) You can extend the BlockParser by registering your own custom block transformers for certain block types, or to override the default transformers: If in the above example you want to add a transformer for some custom block type, you just specify a custom value for the static `$type` property, and then extend the `BlockParser` class and override the `determineBlockType()` method to add your logic for determining when a block is of your custom type; for example:Filter Hooks
Besides creating custom transformers, you can also modify parsed block data using filters. These filters are applied after the block has been transformed by the appropriate transformer, but before the block is returned: The `cloakwp/block` filter accepts two modifiers, `name` and `type`, for more granular targeting: After every ACF field on a block has been formatted — and **before** `cloakwp/block` — you can transform the complete parsed block together with its field definitions: Use this hook to inject derived data (for example resolving a Query group into `data.items`) without replacing a block-level `cloakwp/block` callback. `cloakwp/block` runs after this filter. You can also filter ACF field values within ACF blocks using the `cloakwp/block/field` filter: The `cloakwp/block/field` filter accepts three modifiers, `name` (i.e. ACF field name), `type` (i.e. ACF field type), and `blockName` (i.e. ACF block name), for more granular targeting:Tests
From this package's directory, using PHP 8.4+ and Composer:
Run a focused test or check that tests are independent of execution order:
The suite covers serialized Gutenberg content, nested blocks, synced patterns (including deleted references), custom transformers, WordPress block bindings, hook modifiers and filter order, HTML/query/meta attribute sources, image dimensions, ACF formatting and nested groups, and profiling response headers.
WordPress core is a development-only Composer dependency. The bootstrap loads its real parser, block objects, hooks, REST schema validation, HTML processing, and shortcodes without starting a site. In-memory doubles provide posts, meta, attachments, asset queues, and ACF APIs. ACF tests run in separate processes so their functions cannot affect tests for installations without ACF. No database, Docker, or ACF Pro license is needed. These tests verify this package's handling of ACF results; they do not test ACF Pro's own formatting or a full site's plugins.
tests/Fixtures/ contains saved Gutenberg markup, and tests/Support/ contains
the isolated test environment. To check against another local WordPress version,
set WP_TESTS_CORE_PATH to its core directory (the directory containing
wp-includes) before running composer test.
GitHub Actions runs both adapters with PHPUnit 11 on PHP 8.4 and 8.5, plus PHPUnit 12 on PHP 8.4. Warnings, risky tests, empty suites, and deprecations originating in this package fail the run. Dependency deprecations are excluded from that check.
With Xdebug or PCOV enabled, generate coverage for src/:
Performance comparisons
Structured parsing avoids preliminary HTML rendering unless a block has WordPress
bindings. HTML requested through cloakwp/block/include_rendered is still rendered
by its transformer. If a custom render callback computes attributes that your
integration needs, opt that block into the preliminary render:
ACF's local registry repeatedly scans every registered field to find each parent's children. BlockParser indexes those parent lookups while transforming a block, including rendering, nested blocks, and block filters. ACF still loads complete definitions, expands clones and flexible layouts, and runs its normal field and value filters. The original registry is restored afterward, including on exceptions. The index is reused within the request and refreshed when registry data changes. It does not cache parsed post data or REST responses.
This optimization uses ACF's internal ACF_Data registry. Custom store subclasses
and unsupported query shapes use ACF's original behavior. To disable it for an
integration or compare the same routes with the original lookups:
See benchmarks/README.md for fixed extraction workloads
and pinned before/after comparisons with @cloakwp/benchmark. They supplement
real content routes without changing site content or runtime settings.
All versions of block-parser with dependencies
cloakwp/hook-modifiers Version *
composer/installers Version ^2.2
franzl/studio Version *
tburry/pquery Version ^1.1