verbb / vizy

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

Why do links to other entries/categories/etc. come with the ID as a hash? #188

Closed mattbloomfield closed 1 year ago

mattbloomfield commented 1 year ago

Question

So, this is probably a dumb question. But our authors keep complaining about the appended EntryID on the end of URLs.

e.g. image

At first I thought maybe we had implemented this incorrectly - I understand why Vizy would want to store that ID so it could always reference the right entry despite a slug changing.

But... first of all, that doesn't seem to be happening. From what I can tell it's actually Retour catching that redirect.

And then second of all, why would I ever want that to appear on the frontend? When I dd() the mark all I see is:

[
    'type' => 'link'
    'attrs' => [
        'href' => 'https://uschamber.ddev.site/employment-law/unions/california-enacts-radical-ab-257-restaurant-law#entry:280647@1'
        'target' => ''
        'class' => null
    ]
]

I was hoping there would be something in there with either the Entry ID so I could query it and get the right URL or a clean version.

So I guess my question is what is the expected approach here? How should I be handling links so that they aren't populated with the unnecessary hashes in the frontend?

Additional context

No response

engram-design commented 1 year ago

What version of Vizy are you using? The ref tag certainly isn't meant to be there in the URL, but as you say, it's there to resolve the correct URL for a chosen entry/element when it might change.

We handle this through https://github.com/verbb/vizy/blob/craft-4/src/marks/Link.php#L34 (the same way other plugins do, like Redactor), so something must be failing here.

mattbloomfield commented 1 year ago

I'm using 1.0.21 - maybe it's something in the way we are parsing the JSON?

mattbloomfield commented 1 year ago

I dumped out everything I get from vizy right from the start - even in the rawnode it's still the same I think:

image

And again with the higher level:

image
engram-design commented 1 year ago

The rawNode value will always have that included, as that's representing the value we store in the database - you shouldn't use that for anything for this reason.

How are you outputting your Vizy field content, custom templating or using renderHtml() ?

mattbloomfield commented 1 year ago

Custom templating. Typically we do not use rawNode but we do in a few cases. But in that first screenshot you can see that it still has the value even in the normal marks

engram-design commented 1 year ago

It's still correct behaviour, as rawNode is just the raw data from the database. It's why you'll want to loop through node objects, rather than the rawNode array and use either node.renderHtml() or node.getTag(). I may have to introduce a new node.getHref() method to just get the raw, parsed URL for the href, as that's currently bundled in the getTag() function

mattbloomfield commented 1 year ago

Ok, maybe I'm misunderstanding how this works.

So if I just do a entry.vizyField.all() is that getting the rawNode values?

engram-design commented 1 year ago

It isn't, no, it's prepping the rawNodes from the database (in an array-querier so you can query it like you might with elements), and creating Node and Mark models from the raw data. Through these models, we can transform things a bit from the database - one such thing is to process the links from their raw, saved value to their prepped value.

As the manual render docs show by querying through all the nodes in a field. Links are a little tricky as they're nested within paragraph nodes:

<p class="p-text">
    {% for nodeContent in node.content %}
        {% for mark in nodeContent.marks %}
            {% if mark.type == 'link' %}
                <a class="link" href="{{ mark.attrs.href }}">{{ nodeContent.text }}</a>
            {% elseif mark.type == 'bold' %}
                <strong>{{ nodeContent.text }}</strong>
            {% elseif mark.type == 'italic' %}
                <em>{{ nodeContent.text }}</em>
            {% endif %}
        {% else %}
            {{ nodeContent.text }}
        {% endfor %}
    {% endfor %}
</p>

But the issue with this is that the parsing-reference logic is only there when getTag() is involved. This is called automatically whenever using renderHtml() (or the node or on the field).

Long story short, this parsing logic has now been bundled into the init() function of a Link mark, so that it's parsed immediately. The above code would produce a parsed link. To get this fix early, change your verbb/vizy requirement in composer.json to:

"require": {
  "verbb/vizy": "dev-craft-4 as 2.0.9",
  "...": "..."
}

Then run composer update.

engram-design commented 1 year ago

Fixed in 2.0.10