Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
felixfeng33 committed Dec 14, 2024
1 parent ac88ec4 commit 817234e
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 58 deletions.
2 changes: 1 addition & 1 deletion apps/www/public/r/styles/default/media-demo.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"type": "registry:example"
},
{
"content": "import { jsx } from '@udecode/plate-test-utils';\n\njsx;\n\nexport const imageValue: any = (\n <fragment>\n <hh2>Image</hh2>\n <hp>Add images by either uploading them or providing the image URL:</hp>\n <himg\n align=\"center\"\n url=\"https://images.unsplash.com/photo-1712688930249-98e1963af7bd?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\"\n width=\"55%\"\n >\n <htext />\n </himg>\n <hp>Customize image captions and resize images.</hp>\n </fragment>\n);\n\nexport const mediaPlaceholderValue: any = (\n <fragment>\n <hh2>Upload</hh2>\n <hp>\n Our editor supports various media types for upload, including images,\n videos, audio, and files.\n </hp>\n <hfile\n name=\"sample.pdf\"\n align=\"center\"\n url=\"https://s26.q4cdn.com/900411403/files/doc_downloads/test.pdf\"\n width=\"80%\"\n isUpload\n >\n <htext />\n </hfile>\n <hp indent={1} listStyleType=\"disc\">\n Real-time upload status and progress tracking\n </hp>\n <haudio\n align=\"center\"\n url=\"https://samplelib.com/lib/preview/mp3/sample-3s.mp3\"\n width=\"80%\"\n >\n <htext />\n </haudio>\n <hp indent={1} listStyleType=\"disc\">\n Configurable file size limits and batch upload settings\n </hp>\n <hvideo\n align=\"center\"\n url=\"https://videos.pexels.com/video-files/6769791/6769791-uhd_2560_1440_24fps.mp4\"\n width=\"80%\"\n isUpload\n >\n <htext />\n </hvideo>\n <hp indent={1} listStyleType=\"disc\">\n Clear error messages for any upload issues\n </hp>\n <hp indent={1} listStyleType=\"disc\">\n Try it now - drag an image from your desktop or click the upload button in\n the toolbar\n </hp>\n </fragment>\n);\n\nexport const mediaValue: any = (\n <fragment>\n {imageValue}\n {mediaPlaceholderValue}\n\n <hh2>Embed</hh2>\n <hp>Embed various types of content, such as videos and tweets:</hp>\n <hmediaembed\n align=\"center\"\n url=\"https://www.youtube.com/watch?v=MyiBAziEWUA\"\n >\n <htext />\n </hmediaembed>\n {/* BUG */}\n {/* <hmediaembed\n align=\"center\"\n url=\"https://twitter.com/zbeyens/status/1677214892212776960\"\n >\n <htext />\n </hmediaembed> */}\n </fragment>\n);\n",
"content": "import { jsx } from '@udecode/plate-test-utils';\n\njsx;\n\nexport const imageValue: any = (\n <fragment>\n <hh2>Image</hh2>\n <hp>Add images by either uploading them or providing the image URL:</hp>\n <himg\n align=\"center\"\n caption={[{ children: [{ text: 'Image caption' }] }]}\n url=\"https://images.unsplash.com/photo-1712688930249-98e1963af7bd?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\"\n width=\"55%\"\n >\n <htext />\n </himg>\n <hp>Customize image captions and resize images.</hp>\n </fragment>\n);\n\nexport const mediaPlaceholderValue: any = (\n <fragment>\n <hh2>Upload</hh2>\n <hp>\n Our editor supports various media types for upload, including images,\n videos, audio, and files.\n </hp>\n <hfile\n name=\"sample.pdf\"\n align=\"center\"\n url=\"https://s26.q4cdn.com/900411403/files/doc_downloads/test.pdf\"\n width=\"80%\"\n isUpload\n >\n <htext />\n </hfile>\n <hp indent={1} listStyleType=\"disc\">\n Real-time upload status and progress tracking\n </hp>\n <haudio\n align=\"center\"\n url=\"https://samplelib.com/lib/preview/mp3/sample-3s.mp3\"\n width=\"80%\"\n >\n <htext />\n </haudio>\n <hp indent={1} listStyleType=\"disc\">\n Configurable file size limits and batch upload settings\n </hp>\n <hvideo\n align=\"center\"\n url=\"https://videos.pexels.com/video-files/6769791/6769791-uhd_2560_1440_24fps.mp4\"\n width=\"80%\"\n isUpload\n >\n <htext />\n </hvideo>\n <hp indent={1} listStyleType=\"disc\">\n Clear error messages for any upload issues\n </hp>\n <hp indent={1} listStyleType=\"disc\">\n Try it now - drag an image from your desktop or click the upload button in\n the toolbar\n </hp>\n </fragment>\n);\n\nexport const mediaValue: any = (\n <fragment>\n {imageValue}\n {mediaPlaceholderValue}\n\n <hh2>Embed</hh2>\n <hp>Embed various types of content, such as videos and tweets:</hp>\n <hmediaembed\n align=\"center\"\n url=\"https://www.youtube.com/watch?v=MyiBAziEWUA\"\n >\n <htext />\n </hmediaembed>\n {/* BUG */}\n {/* <hmediaembed\n align=\"center\"\n url=\"https://twitter.com/zbeyens/status/1677214892212776960\"\n >\n <htext />\n </hmediaembed> */}\n </fragment>\n);\n",
"path": "example/values/media-value.tsx",
"target": "components/media-value.tsx",
"type": "registry:example"
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/app/(app)/dev/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ export default async function DevPage() {
});

const html = await serializePlateStatic(editorStatic, staticComponents);
console.log('🚀 ~ DevPage ~ html:', html);
// console.log('🚀 ~ DevPage ~ html:', html);

return (
<div className="mx-auto w-1/2">
Expand Down
184 changes: 184 additions & 0 deletions packages/core/src/lib/static/__tests__/nodes.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import { serializePlateStatic } from '../serializedHtml';
import { createStaticEditor, staticComponents } from './create-static-editor';

describe('serializePlateStatic nodes', () => {
// it('should serialize complex example list with paragraphs to html', async () => {
// const editor = createStaticEditor([
// {
// children: [
// {
// text: 'Some paragraph that contains, ',
// },
// {
// italic: true,
// text: 'italicized text',
// },
// {
// text: ' and ',
// },
// {
// bold: true,
// text: 'bolded text',
// },
// {
// text: ' is first.',
// },
// ],
// type: 'p',
// },
// {
// children: [
// {
// children: [
// {
// children: [
// {
// text: 'Item one in list',
// },
// ],
// type: 'p',
// },
// ],
// type: 'li',
// },
// {
// children: [
// {
// children: [
// {
// text: 'Item two in list',
// },
// ],
// type: 'p',
// },
// ],
// type: 'li',
// },
// ],
// type: 'ul',
// },
// ]);

// const html = await serializePlateStatic(editor, staticComponents, {
// preserveClassNames: [],
// stripClassNames: true,
// stripDataAttributes: true,
// });

// expect(html).toContain(
// '<p>Some paragraph that contains, <em><span>italicized text</span></em> and <strong><span>bolded text</span></strong> is first.</p>'
// );
// expect(html).toContain(
// '<ul><li><p>Item one in list</p></li><li><p>Item two in list</p></li></ul>'
// );
// });

// it('should serialize complex example with no type on top level node to html', async () => {
// const editor = createStaticEditor([
// {
// children: [
// {
// text: 'Some paragraph that contains, ',
// },
// {
// italic: true,
// text: 'italicized text',
// },
// {
// text: ' and ',
// },
// {
// bold: true,
// text: 'bolded text',
// },
// {
// text: ' is first.',
// },
// ],
// type: 'p',
// },
// ]);

// const html = await serializePlateStatic(editor, staticComponents, {
// preserveClassNames: [],
// stripClassNames: true,
// stripDataAttributes: true,
// });

// expect(html).toContain(
// '<p>Some paragraph that contains, <em><span>italicized text</span></em> and <strong><span>bolded text</span></strong> is first.</p>'
// );
// });

// it('should serialize complex example with multiple no types on top level node to html', async () => {
// const editor = createStaticEditor([
// {
// children: [
// {
// text: 'Some paragraph that contains, ',
// },
// {
// italic: true,
// text: 'italicized text',
// },
// {
// text: ' and ',
// },
// {
// bold: true,
// text: 'bolded text',
// },
// {
// text: ' is first.',
// },
// ],
// type: 'p',
// },
// {
// children: [{ bold: true, text: 'FOO' }],
// type: 'p',
// },
// ]);

// const html = await serializePlateStatic(editor, staticComponents, {
// preserveClassNames: [],
// stripClassNames: true,
// stripDataAttributes: true,
// });

// expect(html).toContain(
// '<p>Some paragraph that contains, <em><span>italicized text</span></em> and <strong><span>bolded text</span></strong> is first.</p>'
// );
// expect(html).toContain('<strong><span>FOO</span></strong>');
// });

it('should serialize string with %', async () => {
const editor = createStaticEditor([
{
children: [
{
text: 'None encoded string 100%',
},
],
type: 'p',
},
{
children: [{ text: 'Encoded string 100%25' }],
type: 'p',
},
]);

const html = await serializePlateStatic(editor, staticComponents, {
preserveClassNames: [],
stripClassNames: true,
// stripDataAttributes: true,
});

expect(html).toContain(
'<div data-slate-node="element><span data-slate-leaf="true"><span data-slate-string="true">None encoded string 100%</span></span></div>'
);
// expect(html).toContain(
// '<div><span data-slate-leaf="true"><span data-slate-string="true">Encoded string 100%25</span></span></div>'
// );
});
});
19 changes: 16 additions & 3 deletions packages/core/src/lib/static/components/DefaultStaticLeaf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,25 @@ import React from 'react';
import type { StaticLeafProps } from '../type';

export function PlateStaticLeaf(props: StaticLeafProps) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { as, attributes, children, className, style, ...rest } = props;
const { as, attributes, children, className, leaf, text, ...rest } = props;

const Leaf = (as ?? 'span') as any;

const {
api,
editor,
getOption,
getOptions,
plugin,
setOption,
setOptions,
tf,
type,
...restProps
} = rest as any;

return (
<Leaf className={className} style={style} {...attributes}>
<Leaf className={className} {...attributes} {...restProps}>
{children}
</Leaf>
);
Expand Down
16 changes: 10 additions & 6 deletions packages/core/src/lib/static/components/PlateStatic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,16 @@ function Element({
function Leaf({ editor, leaf = { text: '' }, staticComponents }: LeafProps) {
const renderLeaf = pipeRenderStaticLeaf(editor, staticComponents);

return renderLeaf!({
attributes: { 'data-slate-leaf': true },
children: createStaticString({ text: leaf.text }),
leaf,
text: leaf,
});
return (
<span data-slate-node="text">
{renderLeaf!({
attributes: { 'data-slate-leaf': true },
children: createStaticString({ text: leaf.text }),
leaf,
text: leaf,
})}
</span>
);
}

function PlateViewContent({
Expand Down
42 changes: 2 additions & 40 deletions packages/core/src/lib/static/pipeRenderStaticElement.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,12 @@
import React from 'react';

import type { Path } from 'slate';

import { findNode } from '@udecode/slate';
import clsx from 'clsx';

import type { SlateEditor } from '../editor';
import type { SlatePlugin } from '../plugin';
import type { StaticComponents } from './components';
import type { RenderStaticElement, StaticElementProps } from './type';

import { type SlatePlugin, getEditorPlugin } from '../plugin';
import { getSlateClass, pipeInjectNodeProps } from '../utils';
import { getPluginNodeProps } from '../utils/getPluginNodeProps';
import { PlateStaticElement } from './components/DefaultStaticElement';

export const getRenderStaticNodeProps = ({
editor,
plugin,
props,
}: {
editor: SlateEditor;
props: StaticElementProps;
plugin?: SlatePlugin;
}): StaticElementProps => {
props = getPluginNodeProps(props, plugin);

const { className } = props;

let nodeProps = {
...props,
...(plugin ? getEditorPlugin(editor, plugin) : {}),
className: clsx(getSlateClass(plugin?.node.type), className),
};

nodeProps = pipeInjectNodeProps(
editor,
nodeProps,
(node) => findNode(editor, { match: (n) => n === node })?.[1] as Path
);

if (nodeProps.style && Object.keys(nodeProps.style).length === 0) {
delete nodeProps.style;
}

return nodeProps;
};
import { getRenderStaticNodeProps } from './utils/getRenderStaticNodeProps';

export const getBelowNodesChildren = (
editor: SlateEditor,
Expand Down
15 changes: 9 additions & 6 deletions packages/core/src/lib/static/pipeRenderStaticLeaf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { StaticComponents } from './components';
import type { RenderStaticLeaf } from './type';

import { PlateStaticLeaf } from './components/DefaultStaticLeaf';
import { getRenderStaticNodeProps } from './pipeRenderStaticElement';
import { getRenderStaticNodeProps } from './utils/getRenderStaticNodeProps';

export const pluginRenderStaticLeaf = (
editor: SlateEditor,
Expand All @@ -19,11 +19,14 @@ export const pluginRenderStaticLeaf = (
if (leaf[plugin.node.type ?? plugin.key]) {
const Leaf = staticComponents?.[plugin.key] ?? PlateStaticLeaf;

return (
<Leaf attributes={nodeProps.attributes} leaf={leaf} text={leaf}>
{children}
</Leaf>
);
const ctxProps = getRenderStaticNodeProps({
attributes: leaf.attributes as any,
editor,
plugin,
props: nodeProps as any,
}) as any;

return <Leaf {...ctxProps}>{children}</Leaf>;
}

return children;
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/lib/static/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export type RenderStaticElement<T extends TElement = TElement> = (

export interface TRenderStaticLeafProps<N extends TText = TText> {
attributes: {
'data-slate-leaf': true;
'data-slate-leaf'?: true;
'data-slate-node'?: 'text';
};
children: any;
leaf: N;
Expand Down
46 changes: 46 additions & 0 deletions packages/core/src/lib/static/utils/getRenderStaticNodeProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { AnyObject } from '@udecode/utils';
import type { Path } from 'slate';

import { findNode } from '@udecode/slate';
import clsx from 'clsx';

import type { SlateEditor } from '../../editor';
import type { StaticElementProps } from '../type';

import { type SlatePlugin, getEditorPlugin } from '../../plugin';
import { getSlateClass, pipeInjectNodeProps } from '../../utils';
import { getPluginNodeProps } from '../../utils/getPluginNodeProps';

export const getRenderStaticNodeProps = ({
attributes,
editor,
plugin,
props,
}: {
editor: SlateEditor;
props: StaticElementProps;
attributes?: AnyObject;
plugin?: SlatePlugin;
}): StaticElementProps => {
props = getPluginNodeProps(props, plugin, attributes);

const { className } = props;

let nodeProps = {
...props,
...(plugin ? getEditorPlugin(editor, plugin) : {}),
className: clsx(getSlateClass(plugin?.node.type), className),
};

nodeProps = pipeInjectNodeProps(
editor,
nodeProps,
(node) => findNode(editor, { match: (n) => n === node })?.[1] as Path
);

if (nodeProps.style && Object.keys(nodeProps.style).length === 0) {
delete nodeProps.style;
}

return nodeProps;
};

0 comments on commit 817234e

Please sign in to comment.