Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bard: Object instead of array with raw modifier #11254

Open
carstenjaksch opened this issue Dec 13, 2024 · 7 comments
Open

Bard: Object instead of array with raw modifier #11254

carstenjaksch opened this issue Dec 13, 2024 · 7 comments

Comments

@carstenjaksch
Copy link
Contributor

Bug description

I have a Bard field with a pretty basic structure: h2, h3, p, h3, p, ... (see saved content as markdown at the end)

Using {{ richtext|raw|dump }} outputs an array with the following structure for each other Bard field where I have only one block element (maybe with a hardBreak):

array:1 [▼ // vendor/statamic/cms/src/Modifiers/CoreModifiers.php:622
  0 => array:3 [▼
    "type" => "paragraph"
    "attrs" => array:2 [▼
      "textAlign" => "left"
      "class" => null
    ]
    "content" => array:3 [▼
      0 => array:2 [▼
        "type" => "text"
        "text" => "Ein Anruf genügt – wir kommen kostenlos direkt zu Ihnen und besichtigen Ihr Fahrzeug vor Ort."
      ]
      1 => array:1 [▼
        "type" => "hardBreak"
      ]
      2 => array:3 [▼
        "type" => "text"
        "marks" => array:1 [▶]
        "text" => "Lehnen Sie sich einfach zurück!"
      ]
    ]
  ]
]

But for this special field with more than one block element, the following is returned:

array:1 [▼ // vendor/statamic/cms/src/Modifiers/CoreModifiers.php:622
  0 => 
Statamic\Fields
\
Values {#13243 ▼
    #instance: 
Illuminate\Support
\
Collection {#13246 ▼
      #items: array:2 [▼
        "type" => "text"
        "text" => 
Statamic\Fields
\
Value {#13235 ▼
          -resolver: null
          #raw: "
<h2>Sorgenfrei zur Schadensregulierung – Unfallgutachten von Gutachterix für mehr Entschädigung</h2><h3>100% kostenlos für Unfallgeschädigte</h3><p>Waren Sie in
 ▶
"
          #handle: "text"
          #fieldtype: 
Statamic\Fieldtypes
\
Text {#13232 ▶}
          #augmentable: null
          #shallow: false
        }
      ]
      #escapeWhenCastingToString: false
    }
  }
]

I expect the same structure as for the other Bard fields – with each block element as a separate array in content.

The full markdown content of said field (correct structure):

      richtext:
        -
          type: heading
          attrs:
            textAlign: left
            level: 2
          content:
            -
              type: text
              text: 'Sorgenfrei zur Schadensregulierung – Unfallgutachten von Gutachterix für mehr Entschädigung'
        -
          type: heading
          attrs:
            textAlign: left
            level: 3
          content:
            -
              type: text
              text: '100% kostenlos für Unfallgeschädigte'
        -
          type: paragraph
          attrs:
            textAlign: left
            class: null
          content:
            -
              type: text
              text: 'Waren Sie in einen Unfall verwickelt und sind nicht schuldig? Dann kontaktieren Sie uns, damit wir Sie zu Ihrem Kfz-Schaden technisch beraten. Für die Erstberatung zahlen Sie nichts. Vertrauen Sie uns als neutralen und unabhängigen Kfz-Gutachter.'
        -
          type: heading
          attrs:
            textAlign: left
            level: 3
          content:
            -
              type: text
              text: '38% mehr Entschädigung durch unabhängige Expertise'
        -
          type: paragraph
          attrs:
            textAlign: left
            class: null
          content:
            -
              type: text
              text: 'Sie möchten die maximale Entschädigung für den fremdverschuldeten Unfall, der Sie viele Nerven kostet? Dann vertrauen Sie keinesfalls dem Versicherungsgutachter oder einer Werkstatt. Versicherungen haben ein Interesse daran, entstandene Schäden und Kosten „kleinzureden“ und die Kosten im eigenen Sinne zu drücken. Kostenvoranschläge von Werkstätten betreffen nur die Kosten der Reparatur und lassen die Wertminderung ihres Fahrzeugs und eine Nutzungsausfallentschädigung unberücksichtigt. Wir als unabhängige Sachverständige haben das Ziel, maximale Entschädigungszahlungen für Sie zu erzielen und wollen gerecht das meiste für Sie herausholen – Verlassen Sie sich auf unsere Expertise und langjährige Erfahrung.'
        -
          type: heading
          attrs:
            textAlign: left
            level: 3
          content:
            -
              type: text
              text: '0 km Anfahrtsweg'
        -
          type: paragraph
          attrs:
            textAlign: left
            class: null
          content:
            -
              type: text
              text: 'Unser Team von Gutachterix steht Ihnen von Beginn an zur Seite und erklärt Ihnen alle Details zu den Schäden an Ihrem Wagen. Für die Fahrzeugbesichtigung und Schadenaufnahme kommen wir kostenfrei direkt an Ihren Wunschort, sodass Sie keinen Anfahrtsweg haben. Wir besuchen sie zu Hause, begutachten das Fahrzeug am Unfallort oder fahren zu Ihrem Arbeitsplatz. Als unabhängiger Kfz-Gutachter erstellen wir nicht nur Unfallgutachten und sichern Beweise, sondern stellen auch die Schadenhöhe fest, dokumentieren die Wertminderung oder den Restwert des Fahrzeugs, erstellen Reparaturbestätigungen oder veranschlagen Kosten für Reparaturen. Außerdem kommunizieren wir mit Versicherungen, Anwälten oder Werkstätten und kümmern uns bei Bedarf für Sie um einen Ersatzwagen. Melden Sie sich gerne bei uns, wir beraten Sie!'

How to reproduce

Use more than one block element in Bard and dump the raw data with {{ bard_field|raw|dump }}.

My fieldset config:

title: Fließtext
fields:
  -
    handle: richtext
    field:
      buttons:
        - h2
        - h3
        - h4
        - lead
        - bold
        - italic
        - unorderedlist
        - orderedlist
        - removeformat
        - quote
        - anchor
        - image
        - table
        - alignleft
        - aligncenter
        - alignright
      smart_typography: true
      remove_empty_nodes: true
      type: bard
      display: Fließtext
      localizable: true
      collapse: true
      sets:
        text:
          display: Text
          icon: text-formatting-initial-letter
          sets:
            buttons:
              display: Buttons
              fields:
                -
                  import: button_group

Logs

No response

Environment

Environment
Application Name: Gutachterix
Laravel Version: 11.34.2
PHP Version: 8.3.14
Composer Version: 2.7.7
Environment: local
Debug Mode: ENABLED
URL: gutachterix.test
Maintenance Mode: OFF
Timezone: Europe/Berlin
Locale: en

Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED

Drivers
Broadcasting: reverb
Cache: file
Database: sqlite
Logs: stack / single
Mail: smtp
Queue: sync
Session: file

Statamic
Addons: 7
Sites: 2 (Gutachterix, Clever-Immo)
Stache Watcher: Enabled (auto)
Static Caching: Disabled
Version: 5.42.0 PRO

Statamic Addons
jacksleight/statamic-bard-texstyle: 3.4.1
ryanmitchell/statamic-translation-manager: 2.0.0
statamic/collaboration: 1.0.0
studio1902/statamic-peak-browser-appearance: 3.6.0
studio1902/statamic-peak-commands: 8.12.0
studio1902/statamic-peak-seo: 8.18.0
studio1902/statamic-peak-tools: 6.6.0

Installation

Starter Kit using via CLI

Additional details

No response

@carstenjaksch
Copy link
Contributor Author

I expect the same structure as for the other Bard fields – with each block element as a separate array in content.

That is wrong, was too late yesterday. Of course every block element should have it's own array with a type of heading or paragraph:

array:1 [▼ // vendor/statamic/cms/src/Modifiers/CoreModifiers.php:622
  0 => array:3 [▼
    "type" => "heading"
    "attrs" => array:2 [▼
      "textAlign" => "left"
      "level" => 2
    ]
    "content" => array:3 [▼
      0 => array:2 [▼
        "type" => "text"
        "text" => "Sorgenfrei zur Schadensregulierung – Unfallgutachten von Gutachterix für mehr Entschädigung"
      ]
    ]
  ]
  1 => array:3 [▼
    "type" => "heading"
    "attrs" => array:2 [▼
      "textAlign" => "left"
      "level" => 3
    ]
    "content" => array:3 [▼
      0 => array:2 [▼
        "type" => "text"
        "text" => "100% kostenlos für Unfallgeschädigte"
      ]
    ]
  ]
  2 => array:3 [▼
    "type" => "paragraph"
    "attrs" => array:2 [▼
      "textAlign" => "left"
      "class" => null
    ]
    "content" => array:3 [▼
      0 => array:2 [▼
        "type" => "text"
        "text" => "Waren Sie in ..."
      ]
    ]
  ]
]

@carstenjaksch
Copy link
Contributor Author

This seems to be an edge case where I need to append |raw to the bard field partial data only in a specific component.

I have an accordion partial (WIP):

<div x-data="{
    id: {{ index }},
    get expanded() {
        return this.active === this.id
    },
    set expanded(value) {
        this.active = value ? this.id : null
    },
}" role="region" class="grid {{ view:class }}">
    {{ slot:image }}

    <div class="flex items-center {{ up ? 'flex-col-reverse' : 'flex-col' }}">
        <button
            type="button"
            x-on:click="expanded = !expanded"
            :aria-expanded="expanded"
        >
            {{ if slot:button }}
                {{ slot:button }}
            {{ else }}
                <span x-show="!expanded">{{ accordion:button_open }}</span>
                <span x-show="expanded">{{ accordion:button_close }}</span>
            {{ /if }}
        </button>

        {{ partial:typography/richtext richtext="{accordion:richtext|raw or richtext|raw}" x-show="expanded" x-collapse="" }}
    </div>
</div>

As you can see, the richtext partial needs to pass the data with the raw modifier. I don't know why, that partial is used all over the place and everywhere else I don't need to use that modifier. The richtext partial itself uses it too. That should be sufficient, but it is not in this case:

{{ partial:typography/prose :$as :class="view:class" :when="richtext" }}
    {{ foreach :array="richtext|raw" }}
        <!-- do stuff -->
    {{ /foreach }}
{{ /partial:typography/prose }}

@duncanmcclean
Copy link
Member

How is your accordion setup? Can you provide the YAML for the accordion field(s)?

@carstenjaksch
Copy link
Contributor Author

@duncanmcclean Sure, it just imports the fieldsets:

title: Akkordeon
fields:
  -
    import: button_group
  -
    import: richtext

@duncanmcclean
Copy link
Member

Sorry, I'm not sure I completley understand your issue / how you have things setup (there's lots of partials / fieldsets going on here 😅)....

Are you able to create a fresh Statamic site which clearly demonstrates your issue? 🙂

@carstenjaksch
Copy link
Contributor Author

I think I got it. Explicitly passing a param vs. using the cascade seems to be the issue.

Unfortunately i don't have the time to create a fresh installation for the reproduction, but you can see the issue here: https://github.com/gutacht/statamic/tree/bard

I have prepared resources/view/components/_accordion.antlers.html (link) and resources/view/typography/_richtext.antlers.html (link) for you.

Accordion, lines 40 and 41:

{{ accordion:richtext|raw|dump }}
{{ partial:typography/richtext richtext="{accordion:richtext|raw or richtext|raw}" x-show="expanded" x-collapse="" }}

Richtext also has a |raw|dump of the same variable contents on line 14.

When you visit the home page, you will find the dump output at the top. Open the fourth and fifth array:

Bildschirm­foto 2024-12-18 um 13 21 12

You should see a different structure: The first one of the dump output before passing the contents to the richtext partial and the second one inside the richtext partial.

If you change line 41 of the accordion partial and add a |raw to the richtext param, the array should be the same now.

{{ partial:typography/richtext richtext="{accordion:richtext|raw or richtext|raw}" x-show="expanded" x-collapse="" }}

Richtext is also used in the partial resources/view/page_builder/_icon_grid.antlers.html (link), but here without explicitly passing the richtext param on line 16:

{{ partial:typography/richtext }}

When you add :richtext="richtext" as a param, the output of the icon grid items should disappear:

Bildschirm­foto 2024-12-18 um 13 37 16

Add |raw to the param and it should appear again. That's because of the different array structure.

Conclusion

Using a param with the cascade produces the array structure below with each Bard element in a separate array.

Bildschirm­foto 2024-12-18 um 13 43 15

But passing the Bard content explicitly to a partial, produces an array that contains a Statamic\Fields\Values object with all Bard content as HTML string in one array key:

Bildschirm­foto 2024-12-18 um 13 45 11

I hope the issue is clear now. 😄

@carstenjaksch
Copy link
Contributor Author

I encountered another weird array conversion while getting Bard content.

There is a page with a mounted collection. The page has a replicator page builder which provides content for the collection entries. Here is how I render the page builder contents from the page, if a mounted collection entry is viewed:

Bildschirm­foto 2025-01-02 um 09 59 10

The mounted collection entries have some fields that will be fetched if the corresponding page builder fields are empty.

One of those fetched fields is part of another replicator, because the corresponding fields are also part of a replicator.

This is how I render the accordion page builder set:

Bildschirm­foto 2025-01-02 um 10 06 02

As you can see, I loop through the replicator called accordions and want to set the variable richtext, which will be used by the richtext partial inside the accordion partial.

richtext_accordions is also a replicator (from the mounted collection entry) which has a richtext field of its own. Notice the two dump statements below the variable? This is the output in the browser:

Bildschirm­foto 2025-01-02 um 10 09 47

The array structure changes when I try to access the richtext key directly. This happens with all notations: ['richtext'], :richtext, .richtext.

Well, that should not be a big issue because I already handle that second array structure with the raw modifier in some other places. However, this time raw does not work.

If you need one, I can create another branch as an example. But I think we should complete the other example above first. Maybe this issue gets solved alongside that one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants