Skip to content

Commit 21db058

Browse files
authored
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).
1 parent 90f893a commit 21db058

File tree

3 files changed

+41
-25
lines changed

3 files changed

+41
-25
lines changed

packages/richtext-lexical/src/exports/shared.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ export {
77
objectToFrontmatter,
88
propsToJSXString,
99
} from '../utilities/jsx/jsx.js'
10+
export { hasText } from '../validate/hasText.js'
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import type {
2+
SerializedEditorState,
3+
SerializedLexicalNode,
4+
SerializedParagraphNode,
5+
SerializedTextNode,
6+
} from 'lexical'
7+
8+
export function hasText(
9+
value: null | SerializedEditorState<SerializedLexicalNode> | undefined,
10+
): boolean {
11+
const hasChildren = !!value?.root?.children?.length
12+
13+
let hasOnlyEmptyParagraph = false
14+
if (value?.root?.children?.length === 1) {
15+
if (value?.root?.children[0]?.type === 'paragraph') {
16+
const paragraphNode = value?.root?.children[0] as SerializedParagraphNode
17+
18+
if (!paragraphNode?.children || paragraphNode?.children?.length === 0) {
19+
hasOnlyEmptyParagraph = true
20+
} else if (paragraphNode?.children?.length === 1) {
21+
const paragraphNodeChild = paragraphNode?.children[0]
22+
if (paragraphNodeChild.type === 'text') {
23+
if (!(paragraphNodeChild as SerializedTextNode | undefined)?.['text']?.length) {
24+
hasOnlyEmptyParagraph = true
25+
}
26+
}
27+
}
28+
}
29+
}
30+
31+
if (!hasChildren || hasOnlyEmptyParagraph) {
32+
return false
33+
} else {
34+
return true
35+
}
36+
}

packages/richtext-lexical/src/validate/index.ts

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import type { SerializedEditorState, SerializedParagraphNode, SerializedTextNode } from 'lexical'
1+
import type { SerializedEditorState } from 'lexical'
22
import type { RichTextField, Validate } from 'payload'
33

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

6+
import { hasText } from './hasText.js'
67
import { validateNodes } from './validateNodes.js'
78

89
export const richTextValidateHOC = ({
@@ -19,30 +20,8 @@ export const richTextValidateHOC = ({
1920
required,
2021
} = options
2122

22-
if (required) {
23-
const hasChildren = !!value?.root?.children?.length
24-
25-
let hasOnlyEmptyParagraph = false
26-
if (value?.root?.children?.length === 1) {
27-
if (value?.root?.children[0]?.type === 'paragraph') {
28-
const paragraphNode = value?.root?.children[0] as SerializedParagraphNode
29-
30-
if (!paragraphNode?.children || paragraphNode?.children?.length === 0) {
31-
hasOnlyEmptyParagraph = true
32-
} else if (paragraphNode?.children?.length === 1) {
33-
const paragraphNodeChild = paragraphNode?.children[0]
34-
if (paragraphNodeChild.type === 'text') {
35-
if (!(paragraphNodeChild as SerializedTextNode | undefined)?.['text']?.length) {
36-
hasOnlyEmptyParagraph = true
37-
}
38-
}
39-
}
40-
}
41-
}
42-
43-
if (!hasChildren || hasOnlyEmptyParagraph) {
44-
return t('validation:required')
45-
}
23+
if (required && hasText(value) === false) {
24+
return t('validation:required')
4625
}
4726

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

0 commit comments

Comments
 (0)