Skip to content

Commit

Permalink
feat(richtext-lexical): export hasText helper (#9484)
Browse files Browse the repository at this point in the history
### What?

Extracted `hasText` helper method in `richTextValidateHOC`

### Why?

The new exported `hasText` helper method can now also be used during
front-end serialization - for example, to check whether a caption
element should be rendered when text is optional and therefore possibly
empty (which would allow us to prevent rendering an empty caption
element).
  • Loading branch information
58bits authored Nov 27, 2024
1 parent 90f893a commit 21db058
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 25 deletions.
1 change: 1 addition & 0 deletions packages/richtext-lexical/src/exports/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export {
objectToFrontmatter,
propsToJSXString,
} from '../utilities/jsx/jsx.js'
export { hasText } from '../validate/hasText.js'
36 changes: 36 additions & 0 deletions packages/richtext-lexical/src/validate/hasText.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type {
SerializedEditorState,
SerializedLexicalNode,
SerializedParagraphNode,
SerializedTextNode,
} from 'lexical'

export function hasText(
value: null | SerializedEditorState<SerializedLexicalNode> | undefined,
): boolean {
const hasChildren = !!value?.root?.children?.length

let hasOnlyEmptyParagraph = false
if (value?.root?.children?.length === 1) {
if (value?.root?.children[0]?.type === 'paragraph') {
const paragraphNode = value?.root?.children[0] as SerializedParagraphNode

if (!paragraphNode?.children || paragraphNode?.children?.length === 0) {
hasOnlyEmptyParagraph = true
} else if (paragraphNode?.children?.length === 1) {
const paragraphNodeChild = paragraphNode?.children[0]
if (paragraphNodeChild.type === 'text') {
if (!(paragraphNodeChild as SerializedTextNode | undefined)?.['text']?.length) {
hasOnlyEmptyParagraph = true
}
}
}
}
}

if (!hasChildren || hasOnlyEmptyParagraph) {
return false
} else {
return true
}
}
29 changes: 4 additions & 25 deletions packages/richtext-lexical/src/validate/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { SerializedEditorState, SerializedParagraphNode, SerializedTextNode } from 'lexical'
import type { SerializedEditorState } from 'lexical'
import type { RichTextField, Validate } from 'payload'

import type { SanitizedServerEditorConfig } from '../lexical/config/types.js'

import { hasText } from './hasText.js'
import { validateNodes } from './validateNodes.js'

export const richTextValidateHOC = ({
Expand All @@ -19,30 +20,8 @@ export const richTextValidateHOC = ({
required,
} = options

if (required) {
const hasChildren = !!value?.root?.children?.length

let hasOnlyEmptyParagraph = false
if (value?.root?.children?.length === 1) {
if (value?.root?.children[0]?.type === 'paragraph') {
const paragraphNode = value?.root?.children[0] as SerializedParagraphNode

if (!paragraphNode?.children || paragraphNode?.children?.length === 0) {
hasOnlyEmptyParagraph = true
} else if (paragraphNode?.children?.length === 1) {
const paragraphNodeChild = paragraphNode?.children[0]
if (paragraphNodeChild.type === 'text') {
if (!(paragraphNodeChild as SerializedTextNode | undefined)?.['text']?.length) {
hasOnlyEmptyParagraph = true
}
}
}
}
}

if (!hasChildren || hasOnlyEmptyParagraph) {
return t('validation:required')
}
if (required && hasText(value) === false) {
return t('validation:required')
}

// Traverse through nodes and validate them. Just like a node can hook into the population process (e.g. link or relationship nodes),
Expand Down

0 comments on commit 21db058

Please sign in to comment.