Closed AtmoFX closed 1 month ago
{{ content | bard_items }} fails with a type error:
The bard_items
modifier expects an array, which is what the {{ content }}
field will give you if you create any sets. If you don't have any sets, it just outputs HTML.
I don't think the bard_items
modifier is intended to work without sets.
The ultimate goal is to change the DOM compared to the default behavior of Statamic e.g. render images inside
If you're wanting control over the HTML outputted by Bard, I'd probably create a Bard set for displaying images, instead of using the built-in images feature and trying to override the way it outputs images.
That's what I do on one of my sites:
{{ images }}
<figure>
<img src="{{ url }}" alt="{{ alt }}">
</figure>
{{ /images }}
@duncanmcclean The help page does explicitly say {{ content | raw | bard_items }}
is valid for bard fields without sets, quote:
The raw value from a Bard field (a ProseMirror document), with or without sets
.... but the returned array is unusable like I said: it turns the 3 level-1 nodes of the above sample into 10 nodes (all the subnodes are included) and with some ProseMirror node properties missing (e.g. {{ childCount }}
).
Had the array reproduced the original structure of the document, your solution would be unnecessary.
it turns the 3 level-1 nodes of the above sample into 10 nodes (all the subnodes are included)
This is intentional, from the docs: "Converts any Bard data to a flat array of ProseMirror nodes"
and with some ProseMirror node properties missing
It only returns the raw node data. It doesn't return objects with all the additional properties that the ProseMirrror JS libraries provide, that wouldn’t really be feasible since the PHP library does not provide those properties.
Had the array reproduced the original structure of the document, your solution would be unnecessary.
If you want the original structure you can just use the raw data directly:
{{ nodes = bard_field | raw }}
{{ nodes }}
{{ type }} - {{ content | to_json }}
{{ /nodes }}
I could not find a way to do anything with the JSON. I indeed get it as an array of JSON string and AFAICT, their content is correct but I did not find how to extract the properties from them.
Anyway, I could not help but notice that what I described in the question seemed to look OK to you two whereas I am struggling to even find a purpose to bard_items
. When it does not generate an error (i.e. when used with raw
), it transforms the ProseMirror document so much I do no see how I can possibly process the array.
Surely, there is something I am missing...
I could not find a way to do anything with the JSON. I indeed get it as an array of JSON string and AFAICT, their content is correct but I did not find how to extract the properties from them.
What are you trying to do? If you loop over the raw data as shown above you can access each node's values with {{ type }}
, {{ content }}
, {{ attrs:level }}
etc. However it's pretty unusual to that at all to be honest, the normal way to output a Bard field is to do {{ bard_field }}
and let the augmentation process/Tiptap package convert the nodes to an HTML string for you.
I am struggling to even find a purpose to bard_items.
The bard_items
modifier is intended to be used with other modifiers that expect a flat array of data, eg. if you wanted extract a list of all the headings for a table of contents you could use bard_items
to convert the tree structure to a flat array, and then the where
modifier to filter just the heading nodes. There are some other examples in the docs.
Just wanted to render a field in a different way than the default and only in 1 template
OK. I wouldn't recommend trying to manually loop over nodes to render out each HTML tag, you'd basically be reinventing everything the Tiptap package is already doing. You can customise how Tiptap renders the HTML by implementing your own extensions, or you might want to check out Bard Mutator.
Bug description
I was trying to customize the rendering of a bard field by processing the document's nodes 1 by 1. As per the documentation, the
bard_items
modifier "converts any Bard data to a flat array of ProseMirror nodes and marks". My idea was to browse through the nodes inside document structure as per that other documentation. The ultimate goal is to change the DOM compared to the default behavior of Statamic e.g. render images inside<figure>
tags.It is very possible this exercise is doomed from the start, as bard fields just work fine with native rendering; however, the only purpose I can fathom for the
bard_items
modifier is exactly what I am trying to do.Hopefully, if nodes can be traversed in a sensible way, with recursivity, the feasibility of such approach would be demonstrated. I have inferred from the documentation that recursivity, the same way it is done for NAVs (i.e. `{{ recursive children }}, may not work (that is why nodes are returned in a flat array) but TBH, I could not reach a point where I could test that very part.
The value I try to render is, for illustration, the below value from a bard field configured without sets (I will include what happens with sets below):
I fail to get "a flat array of ProseMirror nodes" using the
bard_items
/raw | bard_items
modifiers. Also, I am getting an error in 1 situation.How to reproduce
Render the provided document with each of the following code snippets:
{{ content }}
works to render the whole bard field at once. When the bard field is configured with sets, then{{ content }}{{ text }}{{ content }}
works for the above document (but obviously would need some{{ type }}
test to correctly render all possible other documents){{ content | bard_items }}
fails with a type error:The complete code for that attempt is:
When the bard field is configured with sets, the above code renders something but as a single block. I actually do not see any difference between
{{ content }}
and{{ content | bard_items }}
in that situation.{{ content | raw | bard_items }}
kind of works but completely breaks down the ProseMirror document structure. The code snippet here is very similar to the one above:The rendered page shows how the
heading
sub-node has no children; rather, the textTitle
is rendered in the next node. The same goes for the paragraphs for which the followingtext
s andhardBreak
are sibling nodes rather that children nodes.It can be argued that
raw | bard_items
returns a flat array but it seems thatbard_items
alone does not do that, contrary to the documentation. As per my tests, I do not think what is returned is ProseMirror nodes. A lot of the documented properties ({{ type }}
,{{ text }}
,{{ attrs }}
, ...) are accessible but not all of them (properties related to nodes children:{{ content }}
,{{ childCount }}
, ... + a few more such asnodeSize
).Logs
No response
Environment
Installation
Fresh statamic/statamic site via CLI
Additional details
No response