diff --git a/apps/server/src/api/v2/reports/[id]/PUT.ts b/apps/server/src/api/v2/reports/[id]/PUT.ts index 30b2aba0d..f300dc4ad 100644 --- a/apps/server/src/api/v2/reports/[id]/PUT.ts +++ b/apps/server/src/api/v2/reports/[id]/PUT.ts @@ -2,6 +2,7 @@ import type { User } from '@buster/database'; import { getUserOrganizationId, updateReport } from '@buster/database'; import type { UpdateReportRequest, UpdateReportResponse } from '@buster/server-shared/reports'; import { UpdateReportRequestSchema } from '@buster/server-shared/reports'; +import { platejsToMarkdown } from '@buster/server-utils/report'; import { zValidator } from '@hono/zod-validator'; import { Hono } from 'hono'; import { HTTPException } from 'hono/http-exception'; @@ -29,7 +30,9 @@ async function updateReportHandler( throw new HTTPException(403, { message: 'User does not have permission to edit asset' }); } - const { name, content, update_version = false } = request; + const { name, content: contentPlateJs, update_version = false } = request; + + const transformedContent = contentPlateJs ? await platejsToMarkdown(contentPlateJs) : undefined; // Update the report in the database await updateReport( @@ -37,7 +40,7 @@ async function updateReportHandler( reportId, userId: user.id, name, - content, + content: transformedContent, }, update_version ); diff --git a/packages/server-utils/src/report/callout-serializer.ts b/packages/server-utils/src/report/callout-serializer.ts index 10aff9360..762c44cb2 100644 --- a/packages/server-utils/src/report/callout-serializer.ts +++ b/packages/server-utils/src/report/callout-serializer.ts @@ -1,22 +1,27 @@ import { type MdNodeParser, convertChildrenDeserialize, - convertNodesSerialize, parseAttributes, + serializeMd, } from '@platejs/markdown'; export const calloutSerializer: MdNodeParser<'callout'> = { serialize: (node, options) => { // Extract the icon from the node (assuming it's stored as an attribute) const icon = node.icon || '💡'; - const content = convertNodesSerialize(node.children, options); - // Return the markdown representation + if (!options.editor) { + throw new Error('Editor is required'); + } + + const content = serializeMd(options.editor, { + ...options, + value: node.children, + }); + return { - attributes: { - icon, - }, - children: content, + type: 'html', + value: `${content}`, }; }, deserialize: (node, deco, options) => { diff --git a/packages/server-utils/src/report/index.ts b/packages/server-utils/src/report/index.ts index f0cb3b1c5..527d8a1d7 100644 --- a/packages/server-utils/src/report/index.ts +++ b/packages/server-utils/src/report/index.ts @@ -1,2 +1,2 @@ -export { markdownToPlatejs } from './markdown-to-platejs'; +export { markdownToPlatejs, platejsToMarkdown } from './platejs-conversions'; export { MarkdownPlugin } from './MarkdownPlugin'; diff --git a/packages/server-utils/src/report/markdown-to-platejs.test.ts b/packages/server-utils/src/report/platejs-conversion.test.ts similarity index 62% rename from packages/server-utils/src/report/markdown-to-platejs.test.ts rename to packages/server-utils/src/report/platejs-conversion.test.ts index 928b74e70..d5ddf03dc 100644 --- a/packages/server-utils/src/report/markdown-to-platejs.test.ts +++ b/packages/server-utils/src/report/platejs-conversion.test.ts @@ -1,5 +1,6 @@ +import type { ReportElements } from '@buster/database'; import { describe, expect, it } from 'vitest'; -import { markdownToPlatejs } from './markdown-to-platejs'; +import { markdownToPlatejs, platejsToMarkdown } from './platejs-conversions'; describe('markdownToPlatejs', () => { it('should convert elaborate markdown to platejs', async () => { @@ -71,3 +72,76 @@ Here's an unordered list: expect(platejs).toBeDefined(); }); }); + +describe('platejsToMarkdown', () => { + it('should convert platejs to markdown', async () => { + const markdown = `This is a simple paragraph.\n`; + const elements: ReportElements = [ + { + type: 'p', + children: [ + { + text: 'This is a simple paragraph.', + }, + ], + }, + ]; + const markdown2 = await platejsToMarkdown(elements); + expect(markdown2).toBe(markdown); + }); + + it('should convert callout platejs element to markdown', async () => { + const elements: ReportElements = [ + { + type: 'h1', + children: [ + { + text: 'Main Title', + }, + ], + }, + { + type: 'p', + children: [ + { + text: 'This paragraph has ', + }, + { + text: 'bold text', + bold: true, + }, + { + text: ' in it.', + }, + ], + }, + ]; + const markdown2 = await platejsToMarkdown(elements); + const markdown = `# Main Title\n\nThis paragraph has **bold text** in it.\n`; + expect(markdown2).toBe(markdown); + }); + + it('should convert callout platejs element to markdown', async () => { + const elements: ReportElements = [ + { + type: 'callout', + icon: '⚠️', + variant: 'warning', + children: [ + { + type: 'p' as const, + children: [ + { + text: 'This is a simple paragraph.', + }, + ], + }, + ], + }, + ]; + const markdownFromPlatejs = await platejsToMarkdown(elements); + + const expectedMarkdown = `This is a simple paragraph.\n\n`; + expect(markdownFromPlatejs).toBe(expectedMarkdown); + }); +}); diff --git a/packages/server-utils/src/report/platejs-conversions.ts b/packages/server-utils/src/report/platejs-conversions.ts new file mode 100644 index 000000000..d17eca7f9 --- /dev/null +++ b/packages/server-utils/src/report/platejs-conversions.ts @@ -0,0 +1,20 @@ +import { type ReportElements, ReportElementsSchema } from '@buster/database'; +import type { Descendant } from 'platejs'; +import { SERVER_EDITOR } from './server-editor'; + +export const markdownToPlatejs = async (markdown: string) => { + const descendants = SERVER_EDITOR.api.markdown.deserialize(markdown); + + const safeParsedElements = ReportElementsSchema.safeParse(descendants); + + return { + error: safeParsedElements.error, + elements: safeParsedElements.data, + descendants, + markdown, + }; +}; + +export const platejsToMarkdown = async (elements: ReportElements): Promise => { + return SERVER_EDITOR.api.markdown.serialize({ value: elements as Descendant[] }); +}; diff --git a/packages/server-utils/src/report/markdown-to-platejs.ts b/packages/server-utils/src/report/server-editor.ts similarity index 70% rename from packages/server-utils/src/report/markdown-to-platejs.ts rename to packages/server-utils/src/report/server-editor.ts index 52b06374d..985f0c02b 100644 --- a/packages/server-utils/src/report/markdown-to-platejs.ts +++ b/packages/server-utils/src/report/server-editor.ts @@ -1,4 +1,3 @@ -import { type ReportElements, ReportElementsSchema } from '@buster/database'; import { AutoformatPlugin } from '@platejs/autoformat'; import { BaseBasicBlocksPlugin, @@ -50,19 +49,6 @@ const serverNode = [ MarkdownPlugin, ]; -const SERVER_EDITOR = createSlateEditor({ +export const SERVER_EDITOR = createSlateEditor({ plugins: serverNode, }); - -export const markdownToPlatejs = async (markdown: string) => { - const descendants = SERVER_EDITOR.api.markdown.deserialize(markdown); - - const safeParsedElements = ReportElementsSchema.safeParse(descendants); - - return { - error: safeParsedElements.error, - elements: safeParsedElements.data, - descendants, - markdown, - }; -};