fix(richtext-lexical)!: html converters not respecting overrideAccess property when populating values, in local API
This commit is contained in:
@@ -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<TData extends TypeWithID = any, TValue = any, TSibling
|
||||
context: RequestContext
|
||||
/** The data passed to update the document within create and update operations, and the full document itself in the afterRead hook. */
|
||||
data?: Partial<TData>
|
||||
/**
|
||||
* 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<TData extends TypeWithID = any, TValue = any, TSibling
|
||||
* The schemaPath of the field, e.g. ["group", "myArray", "textField"]. The schemaPath is the path but without indexes and would be used in the context of field schemas, not field data.
|
||||
*/
|
||||
schemaPath: string[]
|
||||
/**
|
||||
* Only available in the `afterRead` hook.
|
||||
*/
|
||||
showHiddenFields?: boolean
|
||||
/** The sibling data passed to a field that the hook is running against. */
|
||||
siblingData: Partial<TSiblingData>
|
||||
/**
|
||||
|
||||
@@ -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],
|
||||
})
|
||||
|
||||
@@ -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 `<blockquote>${childrenText}</blockquote>`
|
||||
|
||||
@@ -5,15 +5,18 @@ import type { HTMLConverter } from '../types.js'
|
||||
import { convertLexicalNodesToHTML } from '../index.js'
|
||||
|
||||
export const ParagraphHTMLConverter: HTMLConverter<SerializedParagraphNode> = {
|
||||
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 `<p>${childrenText}</p>`
|
||||
},
|
||||
|
||||
@@ -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<string> {
|
||||
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<string> {
|
||||
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 '<span>unknown node</span>'
|
||||
@@ -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)
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
import type { SerializedLexicalNode } from 'lexical'
|
||||
import type { Payload, PayloadRequest } from 'payload'
|
||||
import type { PayloadRequest } from 'payload'
|
||||
|
||||
export type HTMLConverter<T extends SerializedLexicalNode = SerializedLexicalNode> = {
|
||||
converter: ({
|
||||
childIndex,
|
||||
converters,
|
||||
node,
|
||||
parent,
|
||||
req,
|
||||
}: {
|
||||
converter: (args: {
|
||||
childIndex: number
|
||||
converters: HTMLConverter[]
|
||||
converters: HTMLConverter<any>[]
|
||||
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> | string
|
||||
nodeTypes: string[]
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import { createServerFeature } from '../../../utilities/createServerFeature.js'
|
||||
|
||||
export type HTMLConverterFeatureProps = {
|
||||
converters?:
|
||||
| (({ defaultConverters }: { defaultConverters: HTMLConverter[] }) => HTMLConverter[])
|
||||
| HTMLConverter[]
|
||||
| (({ defaultConverters }: { defaultConverters: HTMLConverter<any>[] }) => HTMLConverter<any>[])
|
||||
| HTMLConverter<any>[]
|
||||
}
|
||||
|
||||
// This is just used to save the props on the richText field
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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 `<table class="lexical-table" style="border-collapse: collapse;">${childrenText}</table>`
|
||||
},
|
||||
@@ -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 `<tr class="lexical-table-row">${childrenText}</tr>`
|
||||
},
|
||||
|
||||
@@ -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 + '</' + node?.tag + '>'
|
||||
|
||||
@@ -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"' : ''
|
||||
|
||||
@@ -7,15 +7,18 @@ import type { SerializedListItemNode, SerializedListNode } from './plugin/index.
|
||||
import { convertLexicalNodesToHTML } from '../converters/html/converter/index.js'
|
||||
|
||||
export const ListHTMLConverter: HTMLConverter<SerializedListNode> = {
|
||||
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}</${node?.tag}>`
|
||||
@@ -24,17 +27,20 @@ export const ListHTMLConverter: HTMLConverter<SerializedListNode> = {
|
||||
}
|
||||
|
||||
export const ListItemHTMLConverter: HTMLConverter<SerializedListItemNode> = {
|
||||
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') {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user