verbb / vizy

A flexible visual editor for Craft CMS
Other
43 stars 8 forks source link

GraphQL `VizyMarkInterface` missing `text` field definition and associated text content. #270

Closed javangriff closed 6 months ago

javangriff commented 7 months ago

Describe the bug

When querying marks on a VizyNode for example the VizyNode_Paragraph node type you have access to type, tagName and attrs properties, however, there is no way to return the actual textual content of the mark.

Steps to reproduce

  1. Create a Vizy field with rich-text content on an entry
  2. Create a GraphQL query for the entry with Vizy field included
  3. Add the marks property to the query

Craft CMS version

4.5.11.1

Plugin version

2.1.13

Multi-site?

No

Additional context

No response

engram-design commented 7 months ago

Looks like an oversight on my part, but what I think would be better would be to provide interfaces for content. Currently, we have content which is a collection of nodes that make up the content for a node. So a Paragraph node might consist of several Text nodes, a Link node, List, etc. Those nodes can contain marks like Bold or Italic, but marks themselves don't contain content. They're attached to nodes that contain the textual content.

We provide content which is just the raw JSON-encoded content, which is fine, but it's not structured like an interface object would be. According to the GQL spec, we can't just provide an array of content, which would be neat.

Changing marks would be a breaking change, but it also wouldn't be correct if it contained text nodes - they're not marks.

So for now, I'm deprecating the marks and content attributes, in favour of contentNodes. Actions for the next major version - content will be renamed to rawContent, marks removed, and contentNodes changed to content.

But for now, we have the following text:

Here's some bold text and here's some bold and italic text

This is represented by the following JSON in the database:

[
   {
      "type":"paragraph",
      "content":[
         {
            "type":"text",
            "text":"Here's some "
         },
         {
            "type":"text",
            "marks":[
               {
                  "type":"bold"
               }
            ],
            "text":"bold"
         },
         {
            "type":"text",
            "text":" text and here's some "
         },
         {
            "type":"text",
            "marks":[
               {
                  "type":"bold"
               },
               {
                  "type":"italic"
               }
            ],
            "text":"bold and italic"
         },
         {
            "type":"text",
            "text":" text"
         }
      ]
   }
]

We would query it via GQL as the following:

{
  entry(id: "1234") {
    ... on vizy_vizy_Entry {
      myVizyField {
        nodes {
          type
          contentNodes {
            type
            text
            marks {
              type
            }
          }
        }
      }
    }
  }
}

Producing the following:

{
  "data": {
    "entry": {
      "myVizyField": {
        "nodes": [
          {
            "type": "paragraph",
            "contentNodes": [
              {
                "type": "text",
                "text": "Here's some",
                "marks": []
              },
              {
                "type": "text",
                "text": "bold",
                "marks": [
                  {
                    "type": "bold"
                  }
                ]
              },
              {
                "type": "text",
                "text": "text and here's some",
                "marks": []
              },
              {
                "type": "text",
                "text": "bold and italic",
                "marks": [
                  {
                    "type": "bold"
                  },
                  {
                    "type": "italic"
                  }
                ]
              },
              {
                "type": "text",
                "text": "text",
                "marks": []
              }
            ]
          }
        ]
      }
    }
  }
}

Which almost identically mimics the actual raw content for the field - which is why it'd be sooo much easier if GQL just allowed an array data type. I'll say that you can also JSON-decode the content attribute as well, which is largely the same thing.

Updated for the next release. To get this early, run composer require verbb/vizy:"dev-craft-4 as 2.1.13"

engram-design commented 6 months ago

Fixed in 2.1.14