`core/list-item` content attribute returns html of nested elements
madebyfabian opened this issue · 2 comments
I have created the following block structure in the editor for demo:
My GraphQL query:
GraphQL
query ListPageByUri($uri: ID!) {
page(id: $uri, idType: URI) {
id
title
uri
editorBlocks(flat: true) {
... on CoreList {
name
attributes {
ordered
start
}
}
... on CoreListItem {
name
attributes {
content
}
}
... on CoreParagraph {
name
attributes {
content
className
}
}
}
}
}
Which returns this JSON:
JSON
{
"data": {
"page": {
"id": "cG9zdDoxNDA=",
"title": "Team",
"uri": "/unternehmen/team",
"editorBlocks": [
{
"name": "core/list",
"attributes": {
"ordered": false,
"start": null
}
},
{
"name": "core/list-item",
"attributes": {
"content": "Interesting list item"
}
},
{
"name": "core/list-item",
"attributes": {
"content": "Another one\n<ol>\n<li>Nested ordered</li>\n\n\n\n<li>Another nested ordered\n<ul>\n<li>Deeply nested</li>\n</ul>\n</li>\n</ol>\nNested orderedAnother nested ordered\n<ul>\n<li>Deeply nested</li>\n</ul>\nDeeply nested"
}
},
{
"name": "core/list",
"attributes": {
"ordered": true,
"start": null
}
},
{
"name": "core/list-item",
"attributes": {
"content": "Nested ordered"
}
},
{
"name": "core/list-item",
"attributes": {
"content": "Another nested ordered\n<ul>\n<li>Deeply nested</li>\n</ul>\nDeeply nested"
}
},
{
"name": "core/list",
"attributes": {
"ordered": false,
"start": null
}
},
{
"name": "core/list-item",
"attributes": {
"content": "Deeply nested"
}
},
{
"name": "core/list-item",
"attributes": {
"content": "The funding"
}
},
{
"name": "core/list",
"attributes": {
"ordered": true,
"start": null
}
},
{
"name": "core/list-item",
"attributes": {
"content": "Some numbers\n<ul>\n<li>nested</li>\n</ul>\nnested"
}
},
{
"name": "core/list",
"attributes": {
"ordered": false,
"start": null
}
},
{
"name": "core/list-item",
"attributes": {
"content": "nested"
}
},
{
"name": "core/list-item",
"attributes": {
"content": "Again some numbers"
}
}
]
}
},
"extensions": {
"debug": [
{
"type": "DEBUG_LOGS_INACTIVE",
"message": "GraphQL Debug logging is not active. To see debug logs, GRAPHQL_DEBUG must be enabled."
}
]
}
}
As you can see, it returns every nested item as a block, correctly. But on the attributes.content
field, it includes the HTML for the nested elements.
The current workaround is to just strip the HTML off, but I'd consider this more of a bug.
Thanks for creating this plugin, and thanks in advance!
Hey @madebyfabian. Thanks for the report.
This is the default behavior. As per the core-list-item block.json the contents of the list item is the innerHTML
content of the first <li>
selector.
This is how the block editor saves the content of inner lists in the database. It stores a new list under the current list item.
So each list-item html contents will contain the html content
of the inner list components hence you are seeing that result.
For example given the following list:
This is how it is saved in the database:
<!-- wp:list -->
<ul>
<!-- wp:list-item -->
<li>
Example List 1<!-- wp:list -->
<ul>
<!-- wp:list-item -->
<li>Nested List 1</li>
<!-- /wp:list-item -->
<!-- wp:list-item -->
<li>
Nested List 2<!-- wp:list -->
<ul>
<!-- wp:list-item -->
<li>Inner Nested List 3</li>
<!-- /wp:list-item -->
</ul>
<!-- /wp:list -->
</li>
<!-- /wp:list-item -->
</ul>
<!-- /wp:list -->
</li>
<!-- /wp:list-item -->
</ul>
<!-- /wp:list -->
So when you query the following CoreList
and CoreListItem
component s you get:
"editorBlocks": [
{
"apiVersion": 2,
"name": "core/list",
"renderedHtml": "\n<ul>\n<li>Example List 1\n<ul>\n<li>Nested List 1</li>\n\n\n\n<li>Nested List 2\n<ul>\n<li>Inner Nested List 3</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n",
"clientId": "64d222aabcdf2",
"parentClientId": null,
"attributes": {
"ordered": false,
"start": null
}
},
{
"apiVersion": 2,
"name": "core/list-item",
"renderedHtml": "\n<li>Example List 1\n<ul>\n<li>Nested List 1</li>\n\n\n\n<li>Nested List 2\n<ul>\n<li>Inner Nested List 3</li>\n</ul>\n</li>\n</ul>\n</li>\n",
"clientId": "64d222aabcdf6",
"parentClientId": "64d222aabcdf2",
"attributes": {
"content": "Example List 1\n<ul>\n<li>Nested List 1</li>\n\n\n\n<li>Nested List 2\n<ul>\n<li>Inner Nested List 3</li>\n</ul>\n</li>\n</ul>\nNested List 1Nested List 2\n<ul>\n<li>Inner Nested List 3</li>\n</ul>\nInner Nested List 3"
}
},
{
"apiVersion": 2,
"name": "core/list",
"renderedHtml": "\n<ul>\n<li>Nested List 1</li>\n\n\n\n<li>Nested List 2\n<ul>\n<li>Inner Nested List 3</li>\n</ul>\n</li>\n</ul>\n",
"clientId": "64d222aabcdf7",
"parentClientId": "64d222aabcdf6",
"attributes": {
"ordered": false,
"start": null
}
},
{
"apiVersion": 2,
"name": "core/list-item",
"renderedHtml": "\n<li>Nested List 1</li>\n",
"clientId": "64d222aabcdf8",
"parentClientId": "64d222aabcdf7",
"attributes": {
"content": "Nested List 1"
}
},
{
"apiVersion": 2,
"name": "core/list-item",
"renderedHtml": "\n<li>Nested List 2\n<ul>\n<li>Inner Nested List 3</li>\n</ul>\n</li>\n",
"clientId": "64d222aabcdf9",
"parentClientId": "64d222aabcdf7",
"attributes": {
"content": "Nested List 2\n<ul>\n<li>Inner Nested List 3</li>\n</ul>\nInner Nested List 3"
}
},
{
"apiVersion": 2,
"name": "core/list",
"renderedHtml": "\n<ul>\n<li>Inner Nested List 3</li>\n</ul>\n",
"clientId": "64d222aabcdfa",
"parentClientId": "64d222aabcdf9",
"attributes": {
"ordered": false,
"start": null
}
},
{
"apiVersion": 2,
"name": "core/list-item",
"renderedHtml": "\n<li>Inner Nested List 3</li>\n",
"clientId": "64d222aabcdfb",
"parentClientId": "64d222aabcdfa",
"attributes": {
"content": "Inner Nested List 3"
}
}
]
},
Since the contents of the first list item <li>
for the Example List 1
is another CoreList
block then the content
will be the innerHTML of it.
<li>
------------------------------------------innerHTML Start
Example List 1\n
<ul>
\n
<li>Nested List 1</li>
\n\n\n\n
<li>
Nested List 2\n
<ul>
\n
<li>Inner Nested List 3</li>
\n
</ul>
\n
</li>
\n
</ul>
\nNested List 1Nested List 2\n
<ul>
\n
<li>Inner Nested List 3</li>
\n
</ul>
\nInner Nested List 3
------------------------------------------innerHTML End
Notice that I've used the clientId
and parentClientId
fields in my query. Since the core/list
and core/list-item
components are hierarchical you can use those parameters to put the whole tree together using:
const blocks = flatListToHierarchical(editorBlocks, {childrenKey: "innerBlocks"});
So each block item will contain an innerBlocks
list of blocks that are considered children blocks and we recursively render them using WordPressBlocksViewer
.
This is how we render for example the CoreColumns
and CoreColumn
Blocks in the @faust/blocks package:
https://github.com/wpengine/faustjs/blob/canary/packages/blocks/src/blocks/CoreColumns.tsx#L30-L39
https://github.com/wpengine/faustjs/blob/canary/packages/blocks/src/blocks/CoreColumn.tsx#L30-L39
Hey @theodesp Thanks for your detailed answer. Sorry for the delay. I was not that deep into wordpress, so I thought it was because of WPGraphQL or this Content Blocks extension. I also already do fetch the client Ids and then create the hierarchy out of it. I just thought maybe it would be more "headless" if the html wasn't included. But if that's how it's stored in the DB, we have to strip it away ourselves I think