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

Lexical HTML Converter for field inside block only applied in dev and not in production #7722

Closed
yobottehg opened this issue Aug 16, 2024 · 4 comments
Assignees
Labels
plugin: richtext-lexical @payloadcms/richtext-lexical prioritized

Comments

@yobottehg
Copy link

yobottehg commented Aug 16, 2024

Link to reproduction

No response

Payload Version

3.0.0-beta.78 & 82

Node Version

20 LTS

Next.js Version

15.0.0-beta.87 & 104 & 117

Describe the Bug

Okay this is a really strange issue:

We convert Lexical content to HTML and have a single custom additional LinkHTMLConverter to convert relations to correct http links. It's mostly similiar to this one posted here: #6504 (comment) with some small adjustments for our use case.

If i run payload locally via npm run dev everything is working as it should.
If i run payload in production via build & start the html converter behaves as it would not exist in some circumstances.

When i add a a lexical field directly to a collection or inside a tab everything is working as it should also in production mode.
If I add a lexical field to a block the converter is "skipped" ?

We tested with:
Payload 3.0.0-beta.78 and beta.82 (We checked if it was solved with the importmap)
Next.js 15.0.0-canary.87 and canary.104 and canary.117

I'm unsure on how to describe it better, there is no error in the logs or anything else. It's just as if the code is not there. relations are not converted to http links.

Perhaps someone has. clue / idea what this could be?

Our converters setup looks like this:

    {
      name: 'content',
      label: 'Rich Text',
      type: 'richText',
      localized: true,
      editor: lexicalEditor({
        features: () => [
          BoldFeature(),
          ItalicFeature(),
          StrikethroughFeature(),
          SubscriptFeature(),
          SuperscriptFeature(),
          ParagraphFeature(),
          HeadingFeature({ enabledHeadingSizes: ['h2', 'h3', 'h4', 'h5', 'h6'] }),
          LinkFeature({
            enabledCollections: ['pages', 'documents'],
            fields: ({ defaultFields }: { defaultFields: FieldAffectingData[] }) => [
              ...defaultFields,
              {
                name: 'classes',
                label: 'Style',
                type: 'select',
                hasMany: false,
                defaultValue: 'default',
                required: true,
                options: [
                  { value: 'default', label: 'Default (Text)' },
                  { value: 'button', label: 'Button' },
                  { value: 'button-outline', label: 'Button (outline)' },
                ],
                admin: {
                  description: 'Set how the link will be rendered',
                },
              },
            ],
          }),
          HTMLConverterFeature({
            converters: ({ defaultConverters }) => [...defaultConverters, LinkHTMLConverter],
          }),
          InlineToolbarFeature(),
          UnorderedListFeature(),
          OrderedListFeature(),
          BlockquoteFeature(),
          EXPERIMENTAL_TableFeature(),
        ],
      }),
    },
    lexicalHTML('content', { name: 'content_html' }),

Link converter looks like this:

import {
  HTMLConverter,
  LinkNode,
  SerializedLinkNode,
  convertLexicalNodesToHTML,
  LinkFields,
} from '@payloadcms/richtext-lexical'
import type { PayloadRequest } from 'payload'

const LinkHTMLConverter: HTMLConverter<SerializedLinkNode> = {
  converter: async ({ converters, node, parent, req }) => {
    const childrenText = await convertLexicalNodesToHTML({
      converters,
      lexicalNodes: node.children,
      parent: {
        ...node,
        parent,
      },
      req,
      showHiddenFields: false,
      overrideAccess: false,
      draft: false,
    })
    const { newTab, doc, url, classes, linkType } = node.fields
    // custom links are external if they start with http
    // 'url' can contain a value even if linkType == 'reference'
    const isExternal = linkType === 'custom' && url.startsWith('http')
    const rel = newTab || isExternal ? ' rel="noopener noreferrer"' : ''
    // open external links and documents in new tab
    const target = newTab || isExternal || doc?.relationTo === 'documents' ? ' target="_blank"' : ''
    const className =
      typeof classes === 'string' && classes !== 'default' ? ` class="${classes}"` : ''
    const href = await getLinkHref(node.fields, req)

    return `<a href="${href}"${className}${rel}${target}>${childrenText}</a>`
  },
  nodeTypes: [LinkNode.getType()],
}

const getLinkHref = async (nodeFields: LinkFields, req: PayloadRequest | null) => {
  let href = ''
  const { doc, url, linkType } = nodeFields

  if (linkType === 'custom') {
    href = url
  } else if (typeof doc?.value === 'number' && req) {
    const payloadArgs = {
      depth: 0,
      draft: false,
      req: req,
      showHiddenFields: false,
      id: doc?.value as string,
    }

    switch (doc?.relationTo) {
      case 'pages': {
        const result = await req.payload.findByID({
          ...payloadArgs,
          collection: 'pages',
        })
        const locale = req.locale ?? 'de'
        href = result.paths?.[locale] ?? ''
        break
      }

      case 'documents': {
        const result = await req.payload.findByID({
          ...payloadArgs,
          collection: 'documents',
        })
        href = result.url ?? ''
        break
      }
    }
  }
  return href
}

export default LinkHTMLConverter

Reproduction Steps

Currently working on a reproduction. It's very hard to grasp.

Adapters and Plugins

db-postgres lexical

@yobottehg yobottehg added status: needs-triage Possible bug which hasn't been reproduced yet v3 labels Aug 16, 2024
@AlessioGr AlessioGr self-assigned this Aug 16, 2024
@AlessioGr AlessioGr added the plugin: richtext-lexical @payloadcms/richtext-lexical label Aug 16, 2024
@github-actions github-actions bot removed the status: needs-triage Possible bug which hasn't been reproduced yet label Aug 16, 2024
@yobottehg
Copy link
Author

Some update from my side:

Perhaps this is related to #7743 because if I don't use

const result = await req.payload.findByID({
          ...payloadArgs,
          collection: 'pages',
        })

but:

const page = (await req.payloadDataLoader.load(
      createDataloaderCacheKey({
        collectionSlug: doc?.relationTo,
        currentDepth: 0,
        depth: 1,
        docID: doc?.value as string,
        draft: false,
        fallbackLocale: req.fallbackLocale ?? '',
        locale: req.locale ?? '',
        overrideAccess: false,
        showHiddenFields: false,
        transactionID: req.transactionID!,
      }),

This works also in the production build. Still has the problems from 7743 but at least the code is executed.

@jancbeck
Copy link

Having the same issue.

@yobottehg
Copy link
Author

yobottehg commented Aug 29, 2024

This was a cause of #7743

Copy link
Contributor

github-actions bot commented Sep 6, 2024

This issue has been automatically locked.
Please open a new issue if this issue persists with any additional detail.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
plugin: richtext-lexical @payloadcms/richtext-lexical prioritized
Projects
None yet
Development

No branches or pull requests

4 participants