diff --git a/apps/aurora/app/config/server/content-migrations.server.test.ts b/apps/aurora/app/config/server/content-migrations.server.test.ts new file mode 100644 index 000000000..a6b7ad05e --- /dev/null +++ b/apps/aurora/app/config/server/content-migrations.server.test.ts @@ -0,0 +1,133 @@ +import { afterEach, describe, expect, it } from 'vitest'; +import config from '@plone/registry'; +import { SOMERSAULT_KEY } from '@plone/plate/constants'; +import type { Content, ContentBase } from '@plone/types'; +import installMigrations from './migrations.server'; +import { migrateContent } from './content-migrations.server'; + +type TestContent = Partial & { + '@id': string; + title: string; + blocks: Record; + blocks_layout: { + items: string[]; + }; +}; + +describe('content migrations', () => { + afterEach(() => { + config.settings = {}; + config.blocks = {} as typeof config.blocks; + const utilities = config.utilities as Partial>; + delete utilities.somersaultBlockMigration; + delete utilities.somersaultMigration; + }); + + it('migrates title and legacy value blocks into the somersault block', () => { + config.blocks = { + blocksConfig: {}, + } as typeof config.blocks; + installMigrations(); + + const content: TestContent = { + '@id': 'http://example.com/', + title: 'Page title', + blocks: { + text: { + '@type': 'slate', + value: [{ type: 'p', children: [{ text: 'First block' }] }], + }, + titleBlock: { + '@type': 'title', + }, + }, + blocks_layout: { + items: ['text', 'titleBlock'], + }, + }; + + const migrated = migrateContent(content as unknown as Content); + + expect(migrated.blocks?.[SOMERSAULT_KEY]).toEqual({ + '@type': SOMERSAULT_KEY, + value: [ + { + blockWidth: 'default', + type: 'p', + children: [{ text: 'First block' }], + }, + { + blockWidth: 'default', + type: 'title', + children: [{ text: 'Page title' }], + }, + ], + }); + }); + + it('moves native blocks into the somersault field as unknown nodes', () => { + config.blocks = { + blocksConfig: { + listing: {}, + image: {}, + }, + } as typeof config.blocks; + installMigrations(); + + const content: TestContent = { + '@id': 'http://example.com/', + title: 'Page title', + blocks: { + titleBlock: { + '@type': 'title', + }, + listing: { + '@type': 'listing', + querystring: { + criteria: [], + }, + }, + image: { + '@type': 'image', + url: '/image', + alt: 'Example image', + }, + custom: { + '@type': 'custom-unregistered', + foo: 'bar', + }, + }, + blocks_layout: { + items: ['titleBlock', 'listing', 'image', 'custom'], + }, + }; + + const migrated = migrateContent(content as unknown as Content); + + expect(migrated.blocks?.[SOMERSAULT_KEY]).toEqual({ + '@type': SOMERSAULT_KEY, + value: [ + { + blockWidth: 'default', + type: 'title', + children: [{ text: 'Page title' }], + }, + { + '@type': 'listing', + children: [{ text: '' }], + querystring: { + criteria: [], + }, + type: 'unknown', + }, + { + '@type': 'image', + alt: 'Example image', + children: [{ text: '' }], + type: 'unknown', + url: '/image', + }, + ], + }); + }); +}); diff --git a/apps/aurora/app/config/server/migrations.server.ts b/apps/aurora/app/config/server/migrations.server.ts index 44c3e4500..275dd2086 100644 --- a/apps/aurora/app/config/server/migrations.server.ts +++ b/apps/aurora/app/config/server/migrations.server.ts @@ -12,6 +12,17 @@ import type { SomersaultMigrationArgs, } from '../types'; +const isRegisteredNativeBlock = (block: Record) => { + const blockType = block['@type']; + if (typeof blockType !== 'string') return false; + + const blocksConfig = config.blocks?.blocksConfig as + | Record + | undefined; + + return Boolean(blocksConfig?.[blockType]); +}; + export default function install() { config.registerUtility({ name: 'somersaultBlockMigrationTitle', @@ -38,6 +49,21 @@ export default function install() { Array.isArray(block.value) ? block.value : [], }); + config.registerUtility({ + name: 'somersaultBlockMigrationUnknown', + type: 'somersaultBlockMigration', + method: ({ block }: SomersaultBlockMigrationArgs) => + isRegisteredNativeBlock(block) && !Array.isArray(block.value) + ? [ + { + ...block, + type: 'unknown', + children: [{ text: '' }], + }, + ] + : [], + }); + config.registerUtility({ name: 'somersaultMigrationLegacyBold', type: 'somersaultMigration', diff --git a/apps/aurora/news/+native-blocks-to-somersault.feature b/apps/aurora/news/+native-blocks-to-somersault.feature new file mode 100644 index 000000000..714598b55 --- /dev/null +++ b/apps/aurora/news/+native-blocks-to-somersault.feature @@ -0,0 +1 @@ +Registered Aurora native blocks are now migrated into the Somersault field as `type: 'unknown'` nodes so they can be rendered by the new editor pipeline later. @sneridagh