feat(richtext-lexical): export hasText helper (#9484)

### 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).
This commit is contained in:
Anthony Bouch
2024-11-27 08:22:16 +07:00
committed by GitHub
parent 90f893a558
commit 21db058e2e
3 changed files with 41 additions and 25 deletions

View File

@@ -7,3 +7,4 @@ export {
objectToFrontmatter,
propsToJSXString,
} from '../utilities/jsx/jsx.js'
export { hasText } from '../validate/hasText.js'

View File

@@ -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
}
}

View File

@@ -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 = ({
@@ -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),