nuxt / content

The file-based CMS for your Nuxt application, powered by Markdown and Vue components.
https://content.nuxt.com
MIT License
3.08k stars 624 forks source link

beforeParse with components cause bug #2417

Closed gitFoxCode closed 10 months ago

gitFoxCode commented 10 months ago

Environment


Reproduction

https://stackblitz.com/edit/github-kwkp72

Describe the bug

If a lot of stuff happens during parsing (nuxt-image etc) it bugs things up with cache. Hydration is breaking down, and it causes a lot of additional errors with cache and so on. How can this be programmed correctly so that .replace doesn't cause a "shift" (something like CLS) in content?

Additional context

If custom component eg. "CustomLink.vue" has more HTML elements in it than pure <a> then there are problems. Bug:

   <a :href="`/customlink/${url}`">{{ text }}
        <div class="badge">
            (BADGE TEXT)
        </div>
    </a>

Works:

   <a :href="`/customlink/${url}`">{{ text }}</a>

Logs

No response

nobkd commented 10 months ago

See:

You get hydration mismatches, because around the inserted component, <p>s are generated and therefore break the HTML structure. Inside ps, block elements (like divs) aren't allowed.

Your generated content looks like this:

<div data-content-id="content:index.md">
    <h1 id="nuxt-content">
        Nuxt Content
    </h1>
    <p>
        <a href="/customlink/blahblahblah">
            Some link with custom badge
            <div class="badge"> (BADGE TEXT) </div> <!-- ← <div> inside <p> causes hydration mismatch -->
        </a>.
    </p>
    <!-- ... -->
</div>

If you use a <span> inside your component instead of the <div>, there won't be any hydration mismatch warnings.


Also, the link wouldn't be wrapped by a p if you removed the dot after the component in your markdown: [Some link with custom badge](/superlink/blahblahblah). ← this one


Note Another thing. Why are you using the beforeParse hook to replace the Markdown links? Just to have an example for the unexpected behavior?

If not, you can just overwrite the default link component: (see first paragraph)

  • Create a component somewhere in your components/content directory with the same name as the default component (ProseA.vue)
  • copy the default code from the source
  • update the code to your needs
gitFoxCode commented 10 months ago

@nobkd Thank you for your reply, indeed <span> fixes everything!

Why are you using the beforeParse hook to replace the Markdown links?

In the real project I wanted to create for the blog a link behavior like on wikipedia: when hovering, a window opens with a description of the phrase and so on but actually you are right, I was trying to kill a fly with a bazooka much easier to do it through ProseA 😅