From 8d1179ae1d35a4e405c40cc311dfb852cde9af80 Mon Sep 17 00:00:00 2001 From: Petyo Ivanov Date: Fri, 4 Aug 2023 16:54:31 +0300 Subject: [PATCH 01/15] POC on mdxeditor, content is visible --- package.json | 5 +- .../common/form/FormRichTextField.tsx | 4 + src/components/common/form/MDXEditor.tsx | 86 + tsconfig.json | 19 +- yarn.lock | 2961 ++++++++++++++++- 5 files changed, 3023 insertions(+), 52 deletions(-) create mode 100644 src/components/common/form/MDXEditor.tsx diff --git a/package.json b/package.json index 075d8a105..4e42cfb8a 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@emotion/react": "^11.8.1", "@emotion/server": "^11.4.0", "@emotion/styled": "^11.8.1", + "@mdxeditor/editor": "0.10.0-alpha.1", "@mui/icons-material": "^5.11.11", "@mui/lab": "^5.0.0-alpha.69", "@mui/material": "^5.10.14", @@ -71,6 +72,7 @@ "slick-carousel": "^1.8.1", "slugify": "^1.6.0", "socket.io-client": "^4.5.4", + "turndown": "^7.1.2", "yup": "0.32.9" }, "devDependencies": { @@ -87,6 +89,7 @@ "@types/react-gtm-module": "2.0.0", "@types/react-slick": "^0.23.10", "@types/tryghost__content-api": "^1.3.11", + "@types/turndown": "^5.0.1", "@types/uuid": "^9.0.0", "@types/yup": "0.29.11", "@typescript-eslint/eslint-plugin": "^5.61.0", @@ -109,7 +112,7 @@ "stripe": "^8.184.0", "stylelint": "^15.10.1", "stylelint-config-sass-guidelines": "9.0.1", - "typescript": "4.8.3" + "typescript": "5.1.6" }, "lint-staged": { "*.{ts,tsx,js}": [ diff --git a/src/components/common/form/FormRichTextField.tsx b/src/components/common/form/FormRichTextField.tsx index 8f215c89e..487818878 100644 --- a/src/components/common/form/FormRichTextField.tsx +++ b/src/components/common/form/FormRichTextField.tsx @@ -13,6 +13,7 @@ import ReactQuill, { Quill } from 'react-quill' import BlotFormatter from 'quill-blot-formatter/' import htmlEditButton from 'quill-html-edit-button' +import { ModernEditor } from './MDXEditor' export type FormRichTextFieldProps = { name: string @@ -163,6 +164,8 @@ export default function FormRichTextField({ name }: FormRichTextFieldProps) { {({ field }: { field: FieldInputProps }) => ( + + {/* +*/} )} diff --git a/src/components/common/form/MDXEditor.tsx b/src/components/common/form/MDXEditor.tsx new file mode 100644 index 000000000..31c9e0e85 --- /dev/null +++ b/src/components/common/form/MDXEditor.tsx @@ -0,0 +1,86 @@ +import { MDXEditor } from '@mdxeditor/editor/MDXEditor' +import { DirectiveDescriptor, directivesPlugin } from '@mdxeditor/editor/plugins/directives' +import { imagePlugin } from '@mdxeditor/editor/plugins/image' +import { linkPlugin } from '@mdxeditor/editor/plugins/link' +import { linkDialogPlugin } from '@mdxeditor/editor/plugins/link-dialog' +import { toolbarPlugin } from '@mdxeditor/editor/plugins/toolbar' +import { BoldItalicUnderlineToggles } from '@mdxeditor/editor/plugins/toolbar/components/BoldItalicUnderlineToggles' +import { UndoRedo } from '@mdxeditor/editor/plugins/toolbar/components/UndoRedo' +import { Separator } from '@mdxeditor/editor/plugins/toolbar/primitives/toolbar' +import '@mdxeditor/editor/style.css' +import TurndownService from 'turndown' + +interface ModernEditorProps { + html: string +} + +const turndownService = new TurndownService() + +turndownService.addRule('strikethrough', { + filter: ['iframe'], + replacement: function (_, node) { + const youtubeSrc = (node as HTMLElement).getAttribute('src') + if (!youtubeSrc) { + throw new Error('Found an iframe without a src') + } + const youtubeId = new URL(youtubeSrc).pathname.split('/').at(-1) + return `::youtube{#${youtubeId}}\n` + }, +}) + +export const YoutubeDirectiveDescriptor: DirectiveDescriptor = { + name: 'youtube', + type: 'leafDirective', + testNode(node) { + return node.name === 'youtube' + }, + attributes: ['id'], + hasChildren: false, + Editor: ({ mdastNode, lexicalNode, parentEditor }) => { + return ( +
+ +