From 7cd4a8a6020c7e7e76f69dcefcfd9dedd4ba6755 Mon Sep 17 00:00:00 2001 From: German Jablonski <43938777+GermanJablo@users.noreply.github.com> Date: Fri, 25 Jul 2025 22:58:49 +0100 Subject: [PATCH] fix(richtext-lexical): unify indent between different converters and make paragraphs and lists match without CSS (#13274) Previously, the Lexical editor was using px, and the JSX converter was using rem. #12848 fixed the inconsistency by changing the editor to rem, but it should have been the other way around, changing the JSX converter to px. You can see the latest explanation about why it should be 40px [here](https://github.com/payloadcms/payload/issues/13130#issuecomment-3058348085). In short, that's the default indentation all browsers use for lists. This time I'm making sure to leave clear comments everywhere and a test to avoid another regression. Here is an image of what the e2e test looks like: image The first part is the Lexical editor, the second is the JSX converter. As you can see, the checkbox in JSX looks a little odd because it uses an input checkbox (as opposed to a pseudo-element in the Lexical editor). I thought about adding an inline style to move it slightly to the left, but I found that browsers don't have a standard size for the checkbox; it varies by browser and device. That requires a little more thought; I'll address that in a future PR. Fixes #13130 --- .../src/features/blockquote/server/index.ts | 6 +- .../shared/findConverterForNode.ts | 6 +- .../converter/converters/paragraph.ts | 6 +- .../lexicalToJSX/converter/index.tsx | 6 +- .../jsxConverter/client/plugin/index.tsx | 7 +- .../jsxConverter/client/plugin/style.scss | 12 ++ .../src/features/heading/server/index.ts | 6 +- test/lexical/baseConfig.ts | 2 + .../collections/Lexical/e2e/main/e2e.spec.ts | 11 +- .../LexicalJSXConverter/e2e.spec.ts | 117 ++++++++++++++++++ .../collections/LexicalJSXConverter/index.ts | 18 +++ .../_LexicalFullyFeatured/e2e.spec.ts | 2 +- .../{_LexicalFullyFeatured => }/utils.ts | 23 +++- test/lexical/payload-types.ts | 39 ++++++ test/lexical/slugs.ts | 1 + 15 files changed, 248 insertions(+), 14 deletions(-) create mode 100644 packages/richtext-lexical/src/features/debug/jsxConverter/client/plugin/style.scss create mode 100644 test/lexical/collections/LexicalJSXConverter/e2e.spec.ts create mode 100644 test/lexical/collections/LexicalJSXConverter/index.ts rename test/lexical/collections/{_LexicalFullyFeatured => }/utils.ts (63%) diff --git a/packages/richtext-lexical/src/features/blockquote/server/index.ts b/packages/richtext-lexical/src/features/blockquote/server/index.ts index 96ab9e7919..041da2318a 100644 --- a/packages/richtext-lexical/src/features/blockquote/server/index.ts +++ b/packages/richtext-lexical/src/features/blockquote/server/index.ts @@ -53,7 +53,11 @@ export const BlockquoteFeature = createServerFeature({ }) const style = [ node.format ? `text-align: ${node.format};` : '', - node.indent > 0 ? `padding-inline-start: ${Number(node.indent) * 2}rem;` : '', + // the unit should be px. Do not change it to rem, em, or something else. + // The quantity should be 40px. Do not change it either. + // See rationale in + // https://github.com/payloadcms/payload/issues/13130#issuecomment-3058348085 + node.indent > 0 ? `padding-inline-start: ${node.indent * 40}px;` : '', ] .filter(Boolean) .join(' ') diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml/shared/findConverterForNode.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml/shared/findConverterForNode.ts index 83bde9163d..ebc1e793cd 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml/shared/findConverterForNode.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml/shared/findConverterForNode.ts @@ -83,7 +83,11 @@ export function findConverterForNode< if (!disableIndent && (!Array.isArray(disableIndent) || !disableIndent?.includes(node.type))) { if ('indent' in node && node.indent && node.type !== 'listitem') { - style['padding-inline-start'] = `${Number(node.indent) * 2}rem` + // the unit should be px. Do not change it to rem, em, or something else. + // The quantity should be 40px. Do not change it either. + // See rationale in + // https://github.com/payloadcms/payload/issues/13130#issuecomment-3058348085 + style['padding-inline-start'] = `${Number(node.indent) * 40}px` } } diff --git a/packages/richtext-lexical/src/features/converters/lexicalToHtml_deprecated/converter/converters/paragraph.ts b/packages/richtext-lexical/src/features/converters/lexicalToHtml_deprecated/converter/converters/paragraph.ts index cb737b94ca..5ce159e656 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToHtml_deprecated/converter/converters/paragraph.ts +++ b/packages/richtext-lexical/src/features/converters/lexicalToHtml_deprecated/converter/converters/paragraph.ts @@ -31,7 +31,11 @@ export const ParagraphHTMLConverter: HTMLConverter = { }) const style = [ node.format ? `text-align: ${node.format};` : '', - node.indent > 0 ? `padding-inline-start: ${Number(node.indent) * 2}rem;` : '', + // the unit should be px. Do not change it to rem, em, or something else. + // The quantity should be 40px. Do not change it either. + // See rationale in + // https://github.com/payloadcms/payload/issues/13130#issuecomment-3058348085 + node.indent > 0 ? `padding-inline-start: ${node.indent * 40}px;` : '', ] .filter(Boolean) .join(' ') diff --git a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/index.tsx b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/index.tsx index 15361de29c..772292795c 100644 --- a/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/index.tsx +++ b/packages/richtext-lexical/src/features/converters/lexicalToJSX/converter/index.tsx @@ -139,7 +139,11 @@ export function convertLexicalNodesToJSX({ (!Array.isArray(disableIndent) || !disableIndent?.includes(node.type)) ) { if ('indent' in node && node.indent && node.type !== 'listitem') { - style.paddingInlineStart = `${Number(node.indent) * 2}em` + // the unit should be px. Do not change it to rem, em, or something else. + // The quantity should be 40px. Do not change it either. + // See rationale in + // https://github.com/payloadcms/payload/issues/13130#issuecomment-3058348085 + style.paddingInlineStart = `${Number(node.indent) * 40}px` } } diff --git a/packages/richtext-lexical/src/features/debug/jsxConverter/client/plugin/index.tsx b/packages/richtext-lexical/src/features/debug/jsxConverter/client/plugin/index.tsx index 1553d9fb16..21cadb6191 100644 --- a/packages/richtext-lexical/src/features/debug/jsxConverter/client/plugin/index.tsx +++ b/packages/richtext-lexical/src/features/debug/jsxConverter/client/plugin/index.tsx @@ -5,6 +5,7 @@ import { useEffect, useState } from 'react' // eslint-disable-next-line payload/no-imports-from-exports-dir import { defaultJSXConverters, RichText } from '../../../../../exports/react/index.js' +import './style.scss' export function RichTextPlugin() { const [editor] = useLexicalComposerContext() @@ -16,5 +17,9 @@ export function RichTextPlugin() { }) }, [editor]) - return + return ( +
+ +
+ ) } diff --git a/packages/richtext-lexical/src/features/debug/jsxConverter/client/plugin/style.scss b/packages/richtext-lexical/src/features/debug/jsxConverter/client/plugin/style.scss new file mode 100644 index 0000000000..6f579ce353 --- /dev/null +++ b/packages/richtext-lexical/src/features/debug/jsxConverter/client/plugin/style.scss @@ -0,0 +1,12 @@ +.debug-jsx-converter { + // this is to match the editor component, and be able to compare aligned styles + padding-left: 36px; + + // We revert to the browser defaults (user-agent), because we want to see + // the indentations look good without the need for CSS. + ul, + ol { + padding-left: revert; + margin: revert; + } +} diff --git a/packages/richtext-lexical/src/features/heading/server/index.ts b/packages/richtext-lexical/src/features/heading/server/index.ts index 1da8b1f99c..b7c80a5aec 100644 --- a/packages/richtext-lexical/src/features/heading/server/index.ts +++ b/packages/richtext-lexical/src/features/heading/server/index.ts @@ -71,7 +71,11 @@ export const HeadingFeature = createServerFeature< }) const style = [ node.format ? `text-align: ${node.format};` : '', - node.indent > 0 ? `padding-inline-start: ${Number(node.indent) * 2}rem;` : '', + // the unit should be px. Do not change it to rem, em, or something else. + // The quantity should be 40px. Do not change it either. + // See rationale in + // https://github.com/payloadcms/payload/issues/13130#issuecomment-3058348085 + node.indent > 0 ? `padding-inline-start: ${node.indent * 40}px;` : '', ] .filter(Boolean) .join(' ') diff --git a/test/lexical/baseConfig.ts b/test/lexical/baseConfig.ts index efc7ce8337..fcb2c040eb 100644 --- a/test/lexical/baseConfig.ts +++ b/test/lexical/baseConfig.ts @@ -11,6 +11,7 @@ import { } from './collections/Lexical/index.js' import { LexicalAccessControl } from './collections/LexicalAccessControl/index.js' import { LexicalInBlock } from './collections/LexicalInBlock/index.js' +import { LexicalJSXConverter } from './collections/LexicalJSXConverter/index.js' import { LexicalLinkFeature } from './collections/LexicalLinkFeature/index.js' import { LexicalLocalizedFields } from './collections/LexicalLocalized/index.js' import { LexicalMigrateFields } from './collections/LexicalMigrate/index.js' @@ -30,6 +31,7 @@ export const baseConfig: Partial = { collections: [ LexicalFullyFeatured, LexicalLinkFeature, + LexicalJSXConverter, getLexicalFieldsCollection({ blocks: lexicalBlocks, inlineBlocks: lexicalInlineBlocks, diff --git a/test/lexical/collections/Lexical/e2e/main/e2e.spec.ts b/test/lexical/collections/Lexical/e2e/main/e2e.spec.ts index c85513cc70..5451d54f46 100644 --- a/test/lexical/collections/Lexical/e2e/main/e2e.spec.ts +++ b/test/lexical/collections/Lexical/e2e/main/e2e.spec.ts @@ -1296,24 +1296,23 @@ describe('lexicalMain', () => { await page.getByLabel('Title*').fill('Indent and Text-align') await page.getByRole('paragraph').nth(1).click() await context.grantPermissions(['clipboard-read', 'clipboard-write']) - const getHTMLContent: (indentToSize: (indent: number) => string) => string = (indentToSize) => - `

paragraph centered

Heading right

paragraph without indent

paragraph indent 1

heading indent 2

quote indent 3
` + const htmlContent = `

paragraph centered

Heading right

paragraph without indent

paragraph indent 1

heading indent 2

quote indent 3
` await page.evaluate( async ([htmlContent]) => { - const blob = new Blob([htmlContent as string], { type: 'text/html' }) + const blob = new Blob([htmlContent], { type: 'text/html' }) const clipboardItem = new ClipboardItem({ 'text/html': blob }) await navigator.clipboard.write([clipboardItem]) }, - [getHTMLContent((indent: number) => `${indent * 40}px`)], + [htmlContent], ) // eslint-disable-next-line playwright/no-conditional-in-test const pasteKey = process.platform === 'darwin' ? 'Meta' : 'Control' await page.keyboard.press(`${pasteKey}+v`) await page.locator('#field-richText').click() await page.locator('#field-richText').fill('asd') - await saveDocAndAssert(page) + await page.getByRole('button', { name: 'Save' }).click() await page.getByRole('link', { name: 'API' }).click() - const htmlOutput = page.getByText(getHTMLContent((indent: number) => `${indent * 2}rem`)) + const htmlOutput = page.getByText(htmlContent) await expect(htmlOutput).toBeVisible() }) diff --git a/test/lexical/collections/LexicalJSXConverter/e2e.spec.ts b/test/lexical/collections/LexicalJSXConverter/e2e.spec.ts new file mode 100644 index 0000000000..8a52a7c240 --- /dev/null +++ b/test/lexical/collections/LexicalJSXConverter/e2e.spec.ts @@ -0,0 +1,117 @@ +import type { Locator, Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { AdminUrlUtil } from 'helpers/adminUrlUtil.js' +import { reInitializeDB } from 'helpers/reInitializeDB.js' +import { lexicalJSXConverterSlug } from 'lexical/slugs.js' +import path from 'path' +import { fileURLToPath } from 'url' + +import { ensureCompilationIsDone } from '../../../helpers.js' +import { initPayloadE2ENoConfig } from '../../../helpers/initPayloadE2ENoConfig.js' +import { TEST_TIMEOUT_LONG } from '../../../playwright.config.js' +import { LexicalHelpers } from '../utils.js' +const filename = fileURLToPath(import.meta.url) +const currentFolder = path.dirname(filename) +const dirname = path.resolve(currentFolder, '../../') + +const { beforeAll, beforeEach, describe } = test + +// Unlike other suites, this one runs in parallel, as they run on the `/create` URL and are "pure" tests +test.describe.configure({ mode: 'parallel' }) + +const { serverURL } = await initPayloadE2ENoConfig({ + dirname, +}) + +describe('Lexical JSX Converter', () => { + beforeAll(async ({ browser }, testInfo) => { + testInfo.setTimeout(TEST_TIMEOUT_LONG) + process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit + const page = await browser.newPage() + await ensureCompilationIsDone({ page, serverURL }) + await page.close() + }) + beforeEach(async ({ page }) => { + await reInitializeDB({ + serverURL, + snapshotKey: 'lexicalTest', + uploadsDir: [path.resolve(dirname, './collections/Upload/uploads')], + }) + const url = new AdminUrlUtil(serverURL, lexicalJSXConverterSlug) + const lexical = new LexicalHelpers(page) + await page.goto(url.create) + await lexical.editor.first().focus() + }) + + // See rationale in https://github.com/payloadcms/payload/issues/13130#issuecomment-3058348085 + test('indents should be 40px in the editor and in the jsx converter', async ({ page }) => { + const lexical = new LexicalHelpers(page) + // 40px + await lexical.addLine('ordered', 'HelloA0', 1, false) + await lexical.addLine('paragraph', 'HelloA1', 1) + await lexical.addLine('unordered', 'HelloA2', 1) + await lexical.addLine('h1', 'HelloA3', 1) + await lexical.addLine('check', 'HelloA4', 1) + + // 80px + await lexical.addLine('ordered', 'HelloB0', 2) + await lexical.addLine('paragraph', 'HelloB1', 2) + await lexical.addLine('unordered', 'HelloB2', 2) + await lexical.addLine('h1', 'HelloB3', 2) + await lexical.addLine('check', 'HelloB4', 2) + + const [offsetA0_ed, offsetA0_jsx] = await getIndentOffset(page, 'HelloA0') + const [offsetA1_ed, offsetA1_jsx] = await getIndentOffset(page, 'HelloA1') + const [offsetA2_ed, offsetA2_jsx] = await getIndentOffset(page, 'HelloA2') + const [offsetA3_ed, offsetA3_jsx] = await getIndentOffset(page, 'HelloA3') + const [offsetA4_ed, offsetA4_jsx] = await getIndentOffset(page, 'HelloA4') + + const [offsetB0_ed, offsetB0_jsx] = await getIndentOffset(page, 'HelloB0') + const [offsetB1_ed, offsetB1_jsx] = await getIndentOffset(page, 'HelloB1') + const [offsetB2_ed, offsetB2_jsx] = await getIndentOffset(page, 'HelloB2') + const [offsetB3_ed, offsetB3_jsx] = await getIndentOffset(page, 'HelloB3') + const [offsetB4_ed, offsetB4_jsx] = await getIndentOffset(page, 'HelloB4') + + await expect(() => { + expect(offsetA0_ed).toBe(offsetB0_ed - 40) + expect(offsetA1_ed).toBe(offsetB1_ed - 40) + expect(offsetA2_ed).toBe(offsetB2_ed - 40) + expect(offsetA3_ed).toBe(offsetB3_ed - 40) + expect(offsetA4_ed).toBe(offsetB4_ed - 40) + expect(offsetA0_jsx).toBe(offsetB0_jsx - 40) + expect(offsetA1_jsx).toBe(offsetB1_jsx - 40) + expect(offsetA2_jsx).toBe(offsetB2_jsx - 40) + expect(offsetA3_jsx).toBe(offsetB3_jsx - 40) + // TODO: Checklist item in JSX needs more thought + // expect(offsetA4_jsx).toBe(offsetB4_jsx - 40) + }).toPass() + + // HTML in JSX converter should contain as few inline styles as possible + await expect(async () => { + const innerHTML = await page.locator('.payload-richtext').innerHTML() + const normalized = normalizeCheckboxUUIDs(innerHTML) + expect(normalized).toBe( + `
  1. HelloA0

HelloA1

  • HelloA2

HelloA3

  1. HelloA4
    1. HelloB0

HelloB1

    • HelloB2

HelloB3

`, + ) + }).toPass() + }) +}) + +async function getIndentOffset(page: Page, text: string): Promise<[number, number]> { + const textElement = page.getByText(text) + await expect(textElement).toHaveCount(2) + const startLeft = (locator: Locator) => + locator.evaluate((el) => { + const leftRect = el.getBoundingClientRect().left + const paddingLeft = getComputedStyle(el).paddingLeft + return leftRect + parseFloat(paddingLeft) + }) + return [await startLeft(textElement.first()), await startLeft(textElement.last())] +} + +function normalizeCheckboxUUIDs(html: string): string { + return html + .replace(/id="[a-f0-9-]{36}"/g, 'id="DETERMINISTIC_UUID"') + .replace(/for="[a-f0-9-]{36}"/g, 'for="DETERMINISTIC_UUID"') +} diff --git a/test/lexical/collections/LexicalJSXConverter/index.ts b/test/lexical/collections/LexicalJSXConverter/index.ts new file mode 100644 index 0000000000..60e37ba356 --- /dev/null +++ b/test/lexical/collections/LexicalJSXConverter/index.ts @@ -0,0 +1,18 @@ +import type { CollectionConfig } from 'payload' + +import { DebugJsxConverterFeature, lexicalEditor } from '@payloadcms/richtext-lexical' + +import { lexicalJSXConverterSlug } from '../../slugs.js' + +export const LexicalJSXConverter: CollectionConfig = { + slug: lexicalJSXConverterSlug, + fields: [ + { + name: 'richText', + type: 'richText', + editor: lexicalEditor({ + features: ({ defaultFeatures }) => [...defaultFeatures, DebugJsxConverterFeature()], + }), + }, + ], +} diff --git a/test/lexical/collections/_LexicalFullyFeatured/e2e.spec.ts b/test/lexical/collections/_LexicalFullyFeatured/e2e.spec.ts index ed63640fb5..fa91154386 100644 --- a/test/lexical/collections/_LexicalFullyFeatured/e2e.spec.ts +++ b/test/lexical/collections/_LexicalFullyFeatured/e2e.spec.ts @@ -8,7 +8,7 @@ import { fileURLToPath } from 'url' import { ensureCompilationIsDone } from '../../../helpers.js' import { initPayloadE2ENoConfig } from '../../../helpers/initPayloadE2ENoConfig.js' import { TEST_TIMEOUT_LONG } from '../../../playwright.config.js' -import { LexicalHelpers } from './utils.js' +import { LexicalHelpers } from '../utils.js' const filename = fileURLToPath(import.meta.url) const currentFolder = path.dirname(filename) const dirname = path.resolve(currentFolder, '../../') diff --git a/test/lexical/collections/_LexicalFullyFeatured/utils.ts b/test/lexical/collections/utils.ts similarity index 63% rename from test/lexical/collections/_LexicalFullyFeatured/utils.ts rename to test/lexical/collections/utils.ts index 95030f7fee..560c21379b 100644 --- a/test/lexical/collections/_LexicalFullyFeatured/utils.ts +++ b/test/lexical/collections/utils.ts @@ -8,6 +8,27 @@ export class LexicalHelpers { this.page = page } + async addLine( + type: 'check' | 'h1' | 'h2' | 'ordered' | 'paragraph' | 'unordered', + text: string, + indent: number, + startWithEnter = true, + ) { + if (startWithEnter) { + await this.page.keyboard.press('Enter') + } + await this.slashCommand(type) + // Outdent 10 times to be sure we are at the beginning of the line + for (let i = 0; i < 10; i++) { + await this.page.keyboard.press('Shift+Tab') + } + const adjustedIndent = ['check', 'ordered', 'unordered'].includes(type) ? indent - 1 : indent + for (let i = 0; i < adjustedIndent; i++) { + await this.page.keyboard.press('Tab') + } + await this.page.keyboard.type(text) + } + async save(container: 'document' | 'drawer') { if (container === 'drawer') { await this.drawer.getByText('Save').click() @@ -19,7 +40,7 @@ export class LexicalHelpers { async slashCommand( // prettier-ignore - command: 'block' | 'check' | 'code' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' |'h6' | 'inline' + command: 'block' | 'check' | 'code' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' |'h6' | 'inline' | 'link' | 'ordered' | 'paragraph' | 'quote' | 'relationship' | 'unordered' | 'upload', ) { await this.page.keyboard.press(`/`) diff --git a/test/lexical/payload-types.ts b/test/lexical/payload-types.ts index f6ed02d76b..63f9ecc249 100644 --- a/test/lexical/payload-types.ts +++ b/test/lexical/payload-types.ts @@ -85,6 +85,7 @@ export interface Config { collections: { 'lexical-fully-featured': LexicalFullyFeatured; 'lexical-link-feature': LexicalLinkFeature; + 'lexical-jsx-converter': LexicalJsxConverter; 'lexical-fields': LexicalField; 'lexical-migrate-fields': LexicalMigrateField; 'lexical-localized-fields': LexicalLocalizedField; @@ -105,6 +106,7 @@ export interface Config { collectionsSelect: { 'lexical-fully-featured': LexicalFullyFeaturedSelect | LexicalFullyFeaturedSelect; 'lexical-link-feature': LexicalLinkFeatureSelect | LexicalLinkFeatureSelect; + 'lexical-jsx-converter': LexicalJsxConverterSelect | LexicalJsxConverterSelect; 'lexical-fields': LexicalFieldsSelect | LexicalFieldsSelect; 'lexical-migrate-fields': LexicalMigrateFieldsSelect | LexicalMigrateFieldsSelect; 'lexical-localized-fields': LexicalLocalizedFieldsSelect | LexicalLocalizedFieldsSelect; @@ -205,6 +207,30 @@ export interface LexicalLinkFeature { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "lexical-jsx-converter". + */ +export interface LexicalJsxConverter { + id: string; + richText?: { + root: { + type: string; + children: { + type: string; + version: number; + [k: string]: unknown; + }[]; + direction: ('ltr' | 'rtl') | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + [k: string]: unknown; + } | null; + updatedAt: string; + createdAt: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "lexical-fields". @@ -841,6 +867,10 @@ export interface PayloadLockedDocument { relationTo: 'lexical-link-feature'; value: string | LexicalLinkFeature; } | null) + | ({ + relationTo: 'lexical-jsx-converter'; + value: string | LexicalJsxConverter; + } | null) | ({ relationTo: 'lexical-fields'; value: string | LexicalField; @@ -949,6 +979,15 @@ export interface LexicalLinkFeatureSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "lexical-jsx-converter_select". + */ +export interface LexicalJsxConverterSelect { + richText?: T; + updatedAt?: T; + createdAt?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "lexical-fields_select". diff --git a/test/lexical/slugs.ts b/test/lexical/slugs.ts index 502cec89cf..4ac5859431 100644 --- a/test/lexical/slugs.ts +++ b/test/lexical/slugs.ts @@ -2,6 +2,7 @@ export const usersSlug = 'users' export const lexicalFullyFeaturedSlug = 'lexical-fully-featured' export const lexicalFieldsSlug = 'lexical-fields' +export const lexicalJSXConverterSlug = 'lexical-jsx-converter' export const lexicalLinkFeatureSlug = 'lexical-link-feature' export const lexicalLocalizedFieldsSlug = 'lexical-localized-fields'