diff --git a/packages/payload/src/fields/config/types.ts b/packages/payload/src/fields/config/types.ts index 20ac7d615..6b053f9c9 100644 --- a/packages/payload/src/fields/config/types.ts +++ b/packages/payload/src/fields/config/types.ts @@ -7,7 +7,6 @@ import type { CSSProperties } from 'react' import monacoeditor from 'monaco-editor' // IMPORTANT - DO NOT REMOVE: This is required for pnpm's default isolated mode to work - even though the import is not used. This is due to a typescript bug: https://github.com/microsoft/TypeScript/issues/47663#issuecomment-1519138189. (tsbugisolatedmode) import type { JSONSchema4 } from 'json-schema' import type React from 'react' -import type { DeepPartial } from 'ts-essentials' import type { RichTextAdapter, RichTextAdapterProvider } from '../../admin/RichText.js' import type { ErrorComponent } from '../../admin/forms/Error.js' @@ -33,6 +32,10 @@ export type FieldHookArgs + /** + * Only available in the `afterRead` hook. + */ + draft?: boolean /** The field which the hook is running against. */ field: FieldAffectingData /** Boolean to denote if this hook is running against finding one, or finding many within the afterRead hook. */ @@ -60,6 +63,10 @@ export type FieldHookArgs /** diff --git a/packages/payload/src/fields/hooks/afterRead/promise.ts b/packages/payload/src/fields/hooks/afterRead/promise.ts index bd04e7ae2..ff9fc3878 100644 --- a/packages/payload/src/fields/hooks/afterRead/promise.ts +++ b/packages/payload/src/fields/hooks/afterRead/promise.ts @@ -205,6 +205,7 @@ export const promise = async ({ collection, context, data: doc, + draft, field, findMany, global, @@ -214,6 +215,7 @@ export const promise = async ({ path: fieldPath, req, schemaPath: fieldSchemaPath, + showHiddenFields, siblingData: siblingDoc, value, }) @@ -230,6 +232,7 @@ export const promise = async ({ collection, context, data: doc, + draft, field, findMany, global, @@ -239,6 +242,7 @@ export const promise = async ({ path: fieldPath, req, schemaPath: fieldSchemaPath, + showHiddenFields, siblingData: siblingDoc, value: siblingDoc[field.name], }) diff --git a/packages/richtext-lexical/src/features/blockquote/feature.server.ts b/packages/richtext-lexical/src/features/blockquote/feature.server.ts index dba566416..8261cc076 100644 --- a/packages/richtext-lexical/src/features/blockquote/feature.server.ts +++ b/packages/richtext-lexical/src/features/blockquote/feature.server.ts @@ -28,15 +28,26 @@ export const BlockquoteFeature = createServerFeature({ createNode({ converters: { html: { - converter: async ({ converters, node, parent, req }) => { + converter: async ({ + converters, + draft, + node, + overrideAccess, + parent, + req, + showHiddenFields, + }) => { const childrenText = await convertLexicalNodesToHTML({ converters, + draft, lexicalNodes: node.children, + overrideAccess, parent: { ...node, parent, }, req, + showHiddenFields, }) return `
${childrenText}
` diff --git a/packages/richtext-lexical/src/features/converters/html/converter/converters/paragraph.ts b/packages/richtext-lexical/src/features/converters/html/converter/converters/paragraph.ts index 556f86676..fbc9fa9b6 100644 --- a/packages/richtext-lexical/src/features/converters/html/converter/converters/paragraph.ts +++ b/packages/richtext-lexical/src/features/converters/html/converter/converters/paragraph.ts @@ -5,15 +5,18 @@ import type { HTMLConverter } from '../types.js' import { convertLexicalNodesToHTML } from '../index.js' export const ParagraphHTMLConverter: HTMLConverter = { - async converter({ converters, node, parent, req }) { + async converter({ converters, draft, node, overrideAccess, parent, req, showHiddenFields }) { const childrenText = await convertLexicalNodesToHTML({ converters, + draft, lexicalNodes: node.children, + overrideAccess, parent: { ...node, parent, }, req, + showHiddenFields, }) return `

${childrenText}

` }, diff --git a/packages/richtext-lexical/src/features/converters/html/converter/index.ts b/packages/richtext-lexical/src/features/converters/html/converter/index.ts index 0aee498fa..6cd80fe00 100644 --- a/packages/richtext-lexical/src/features/converters/html/converter/index.ts +++ b/packages/richtext-lexical/src/features/converters/html/converter/index.ts @@ -8,6 +8,9 @@ import type { HTMLConverter, SerializedLexicalNodeWithParent } from './types.js' export type ConvertLexicalToHTMLArgs = { converters: HTMLConverter[] data: SerializedEditorState + draft?: boolean // default false + overrideAccess?: boolean // default false + showHiddenFields?: boolean // default false } & ( | { /** @@ -40,8 +43,11 @@ export type ConvertLexicalToHTMLArgs = { export async function convertLexicalToHTML({ converters, data, + draft, + overrideAccess, payload, req, + showHiddenFields, }: ConvertLexicalToHTMLArgs): Promise { if (data?.root?.children?.length) { if (req === undefined && payload) { @@ -50,9 +56,12 @@ export async function convertLexicalToHTML({ return await convertLexicalNodesToHTML({ converters, + draft: draft === undefined ? false : draft, lexicalNodes: data?.root?.children, + overrideAccess: overrideAccess === undefined ? false : overrideAccess, parent: data?.root, req, + showHiddenFields: showHiddenFields === undefined ? false : showHiddenFields, }) } return '' @@ -60,17 +69,23 @@ export async function convertLexicalToHTML({ export async function convertLexicalNodesToHTML({ converters, + draft, lexicalNodes, + overrideAccess, parent, req, + showHiddenFields, }: { converters: HTMLConverter[] + draft: boolean lexicalNodes: SerializedLexicalNode[] + overrideAccess: boolean parent: SerializedLexicalNodeWithParent /** * When the converter is called, req CAN be passed in depending on where it's run. */ req: PayloadRequest | null + showHiddenFields: boolean }): Promise { const unknownConverter = converters.find((converter) => converter.nodeTypes.includes('unknown')) @@ -85,9 +100,12 @@ export async function convertLexicalNodesToHTML({ return await unknownConverter.converter({ childIndex: i, converters, + draft, node, + overrideAccess, parent, req, + showHiddenFields, }) } return 'unknown node' @@ -95,9 +113,12 @@ export async function convertLexicalNodesToHTML({ return await converterForNode.converter({ childIndex: i, converters, + draft, node, + overrideAccess, parent, req, + showHiddenFields, }) } catch (error) { console.error('Error converting lexical node to HTML:', error, 'node:', node) diff --git a/packages/richtext-lexical/src/features/converters/html/converter/types.ts b/packages/richtext-lexical/src/features/converters/html/converter/types.ts index a9d7a3e08..043f5d491 100644 --- a/packages/richtext-lexical/src/features/converters/html/converter/types.ts +++ b/packages/richtext-lexical/src/features/converters/html/converter/types.ts @@ -1,22 +1,19 @@ import type { SerializedLexicalNode } from 'lexical' -import type { Payload, PayloadRequest } from 'payload' +import type { PayloadRequest } from 'payload' export type HTMLConverter = { - converter: ({ - childIndex, - converters, - node, - parent, - req, - }: { + converter: (args: { childIndex: number - converters: HTMLConverter[] + converters: HTMLConverter[] + draft: boolean node: T + overrideAccess: boolean parent: SerializedLexicalNodeWithParent /** * When the converter is called, req CAN be passed in depending on where it's run. */ req: PayloadRequest | null + showHiddenFields: boolean }) => Promise | string nodeTypes: string[] } diff --git a/packages/richtext-lexical/src/features/converters/html/feature.server.ts b/packages/richtext-lexical/src/features/converters/html/feature.server.ts index 0573da05f..6696844e7 100644 --- a/packages/richtext-lexical/src/features/converters/html/feature.server.ts +++ b/packages/richtext-lexical/src/features/converters/html/feature.server.ts @@ -4,8 +4,8 @@ import { createServerFeature } from '../../../utilities/createServerFeature.js' export type HTMLConverterFeatureProps = { converters?: - | (({ defaultConverters }: { defaultConverters: HTMLConverter[] }) => HTMLConverter[]) - | HTMLConverter[] + | (({ defaultConverters }: { defaultConverters: HTMLConverter[] }) => HTMLConverter[]) + | HTMLConverter[] } // This is just used to save the props on the richText field diff --git a/packages/richtext-lexical/src/features/converters/html/field/index.ts b/packages/richtext-lexical/src/features/converters/html/field/index.ts index b6f125030..90b9e2151 100644 --- a/packages/richtext-lexical/src/features/converters/html/field/index.ts +++ b/packages/richtext-lexical/src/features/converters/html/field/index.ts @@ -160,7 +160,16 @@ export const lexicalHTML: ( }, hooks: { afterRead: [ - async ({ collection, field, global, req, siblingData }) => { + async ({ + collection, + draft, + field, + global, + overrideAccess, + req, + showHiddenFields, + siblingData, + }) => { const fields = collection ? collection.fields : global.fields const foundSiblingFields = findFieldPathAndSiblingFields(fields, [], field) @@ -209,7 +218,10 @@ export const lexicalHTML: ( return await convertLexicalToHTML({ converters: finalConverters, data: lexicalFieldData, + draft, + overrideAccess, req, + showHiddenFields, }) }, ], diff --git a/packages/richtext-lexical/src/features/experimental_table/feature.server.ts b/packages/richtext-lexical/src/features/experimental_table/feature.server.ts index 11c98824a..3f0a8684e 100644 --- a/packages/richtext-lexical/src/features/experimental_table/feature.server.ts +++ b/packages/richtext-lexical/src/features/experimental_table/feature.server.ts @@ -46,15 +46,26 @@ export const EXPERIMENTAL_TableFeature = createServerFeature({ createNode({ converters: { html: { - converter: async ({ converters, node, parent, req }) => { + converter: async ({ + converters, + draft, + node, + overrideAccess, + parent, + req, + showHiddenFields, + }) => { const childrenText = await convertLexicalNodesToHTML({ converters, + draft, lexicalNodes: node.children, + overrideAccess, parent: { ...node, parent, }, req, + showHiddenFields, }) return `${childrenText}
` }, @@ -66,15 +77,26 @@ export const EXPERIMENTAL_TableFeature = createServerFeature({ createNode({ converters: { html: { - converter: async ({ converters, node, parent, req }) => { + converter: async ({ + converters, + draft, + node, + overrideAccess, + parent, + req, + showHiddenFields, + }) => { const childrenText = await convertLexicalNodesToHTML({ converters, + draft, lexicalNodes: node.children, + overrideAccess, parent: { ...node, parent, }, req, + showHiddenFields, }) const tagName = node.headerState > 0 ? 'th' : 'td' @@ -95,15 +117,26 @@ export const EXPERIMENTAL_TableFeature = createServerFeature({ createNode({ converters: { html: { - converter: async ({ converters, node, parent, req }) => { + converter: async ({ + converters, + draft, + node, + overrideAccess, + parent, + req, + showHiddenFields, + }) => { const childrenText = await convertLexicalNodesToHTML({ converters, + draft, lexicalNodes: node.children, + overrideAccess, parent: { ...node, parent, }, req, + showHiddenFields, }) return `${childrenText}` }, diff --git a/packages/richtext-lexical/src/features/heading/feature.server.ts b/packages/richtext-lexical/src/features/heading/feature.server.ts index 70490ad7b..da4001f87 100644 --- a/packages/richtext-lexical/src/features/heading/feature.server.ts +++ b/packages/richtext-lexical/src/features/heading/feature.server.ts @@ -46,15 +46,26 @@ export const HeadingFeature = createServerFeature< createNode({ converters: { html: { - converter: async ({ converters, node, parent, req }) => { + converter: async ({ + converters, + draft, + node, + overrideAccess, + parent, + req, + showHiddenFields, + }) => { const childrenText = await convertLexicalNodesToHTML({ converters, + draft, lexicalNodes: node.children, + overrideAccess, parent: { ...node, parent, }, req, + showHiddenFields, }) return '<' + node?.tag + '>' + childrenText + '' diff --git a/packages/richtext-lexical/src/features/link/feature.server.ts b/packages/richtext-lexical/src/features/link/feature.server.ts index a4f3087ca..73e1009d9 100644 --- a/packages/richtext-lexical/src/features/link/feature.server.ts +++ b/packages/richtext-lexical/src/features/link/feature.server.ts @@ -116,15 +116,26 @@ export const LinkFeature = createServerFeature< createNode({ converters: { html: { - converter: async ({ converters, node, parent, req }) => { + converter: async ({ + converters, + draft, + node, + overrideAccess, + parent, + req, + showHiddenFields, + }) => { const childrenText = await convertLexicalNodesToHTML({ converters, + draft, lexicalNodes: node.children, + overrideAccess, parent: { ...node, parent, }, req, + showHiddenFields, }) const rel: string = node.fields.newTab ? ' rel="noopener noreferrer"' : '' @@ -150,15 +161,26 @@ export const LinkFeature = createServerFeature< createNode({ converters: { html: { - converter: async ({ converters, node, parent, req }) => { + converter: async ({ + converters, + draft, + node, + overrideAccess, + parent, + req, + showHiddenFields, + }) => { const childrenText = await convertLexicalNodesToHTML({ converters, + draft, lexicalNodes: node.children, + overrideAccess, parent: { ...node, parent, }, req, + showHiddenFields, }) const rel: string = node.fields.newTab ? ' rel="noopener noreferrer"' : '' diff --git a/packages/richtext-lexical/src/features/lists/htmlConverter.ts b/packages/richtext-lexical/src/features/lists/htmlConverter.ts index 6f50d8c60..6671bd140 100644 --- a/packages/richtext-lexical/src/features/lists/htmlConverter.ts +++ b/packages/richtext-lexical/src/features/lists/htmlConverter.ts @@ -7,15 +7,18 @@ import type { SerializedListItemNode, SerializedListNode } from './plugin/index. import { convertLexicalNodesToHTML } from '../converters/html/converter/index.js' export const ListHTMLConverter: HTMLConverter = { - converter: async ({ converters, node, parent, req }) => { + converter: async ({ converters, draft, node, overrideAccess, parent, req, showHiddenFields }) => { const childrenText = await convertLexicalNodesToHTML({ converters, + draft, lexicalNodes: node.children, + overrideAccess, parent: { ...node, parent, }, req, + showHiddenFields, }) return `<${node?.tag} class="list-${node?.listType}">${childrenText}` @@ -24,17 +27,20 @@ export const ListHTMLConverter: HTMLConverter = { } export const ListItemHTMLConverter: HTMLConverter = { - converter: async ({ converters, node, parent, req }) => { + converter: async ({ converters, draft, node, overrideAccess, parent, req, showHiddenFields }) => { const hasSubLists = node.children.some((child) => child.type === 'list') const childrenText = await convertLexicalNodesToHTML({ converters, + draft, lexicalNodes: node.children, + overrideAccess, parent: { ...node, parent, }, req, + showHiddenFields, }) if ('listType' in parent && parent?.listType === 'check') { diff --git a/packages/richtext-lexical/src/features/upload/feature.server.ts b/packages/richtext-lexical/src/features/upload/feature.server.ts index 388a77594..7c4486155 100644 --- a/packages/richtext-lexical/src/features/upload/feature.server.ts +++ b/packages/richtext-lexical/src/features/upload/feature.server.ts @@ -99,7 +99,7 @@ export const UploadFeature = createServerFeature< createNode({ converters: { html: { - converter: async ({ node, req }) => { + converter: async ({ draft, node, overrideAccess, req, showHiddenFields }) => { // @ts-expect-error const id = node?.value?.id || node?.value // for backwards-compatibility @@ -115,11 +115,11 @@ export const UploadFeature = createServerFeature< currentDepth: 0, data: uploadDocument, depth: 1, - draft: false, + draft, key: 'value', - overrideAccess: false, + overrideAccess, req, - showHiddenFields: false, + showHiddenFields, }) } catch (ignored) { // eslint-disable-next-line no-console diff --git a/test/fields/payload-types.ts b/test/fields/payload-types.ts index b661b4f45..192ae24f4 100644 --- a/test/fields/payload-types.ts +++ b/test/fields/payload-types.ts @@ -74,6 +74,7 @@ export interface Config { export interface UserAuthOperations { forgotPassword: { email: string; + password: string; }; login: { email: string; @@ -85,6 +86,7 @@ export interface UserAuthOperations { }; unlock: { email: string; + password: string; }; } /**