diff --git a/package-lock.json b/package-lock.json index 1c347a6..4071f65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,6 @@ "react-toastify": "10.0.5", "react-window": "1.8.10", "swiper": "11.1.11", - "turndown": "^7.2.0", "uuid": "10.0.0", "webln": "0.3.2" }, @@ -2058,12 +2057,6 @@ "react-dom": ">= 18 || >= 19" } }, - "node_modules/@mixmark-io/domino": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz", - "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==", - "license": "BSD-2-Clause" - }, "node_modules/@noble/ciphers": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.5.3.tgz", @@ -8037,15 +8030,6 @@ "resolved": "https://registry.npmjs.org/tstl/-/tstl-2.5.16.tgz", "integrity": "sha512-+O2ybLVLKcBwKm4HymCEwZIT0PpwS3gCYnxfSDEjJEKADvIFruaQjd3m7CAKNU1c7N3X3WjVz87re7TA2A5FUw==" }, - "node_modules/turndown": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz", - "integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==", - "license": "MIT", - "dependencies": { - "@mixmark-io/domino": "^2.2.0" - } - }, "node_modules/type": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", diff --git a/package.json b/package.json index 8ac96df..0dfffbf 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,6 @@ "react-toastify": "10.0.5", "react-window": "1.8.10", "swiper": "11.1.11", - "turndown": "^7.2.0", "uuid": "10.0.0", "webln": "0.3.2" }, diff --git a/src/components/Markdown/Editor.tsx b/src/components/Markdown/Editor.tsx index 45bea77..f2baa8d 100644 --- a/src/components/Markdown/Editor.tsx +++ b/src/components/Markdown/Editor.tsx @@ -4,6 +4,8 @@ import { codeBlockPlugin, CodeToggle, CreateLink, + diffSourcePlugin, + DiffSourceToggleWrapper, directivesPlugin, headingsPlugin, imagePlugin, @@ -68,34 +70,42 @@ export const Editor = React.memo( () => [ toolbarPlugin({ toolbarContents: () => ( - <> - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - + - - + + - - - + + + + } + /> ) }), headingsPlugin(), + diffSourcePlugin({ + viewMode: 'rich-text', + diffMarkdown: markdown + }), quotePlugin(), imagePlugin({ ImageDialog: ImageDialog @@ -118,6 +128,7 @@ export const Editor = React.memo( codeBlockEditorDescriptors: [PlainTextCodeEditorDescriptor] }) ], + // eslint-disable-next-line react-hooks/exhaustive-deps [] ) diff --git a/src/components/ModForm.tsx b/src/components/ModForm.tsx index afeccd5..a4a86cd 100644 --- a/src/components/ModForm.tsx +++ b/src/components/ModForm.tsx @@ -22,7 +22,12 @@ import { ModPageLoaderResult, SubmitModActionResult } from '../types' -import { initializeFormState, MOD_DRAFT_CACHE_KEY } from '../utils' +import { + initializeFormState, + log, + LogType, + MOD_DRAFT_CACHE_KEY +} from '../utils' import { CheckboxField, InputField, InputFieldWithImageUpload } from './Inputs' import { OriginalAuthor } from './OriginalAuthor' import { CategoryAutocomplete } from './CategoryAutocomplete' @@ -32,6 +37,7 @@ import { MEDIA_OPTIONS } from 'controllers' import { InputError } from './Inputs/Error' import { ImageUpload } from './Inputs/ImageUpload' import { useLocalCache } from 'hooks/useLocalCache' +import { toast } from 'react-toastify' interface GameOption { value: string @@ -59,6 +65,13 @@ export const ModForm = () => { isEditing ? initializeFormState(mod) : cache ? cache : initializeFormState() ) + // Enable backwards compatibility with the mods that used html + const body = useMemo(() => { + // Replace the most problematic HTML tags (
) + const fixed = formState.body.replaceAll(/
/g, '\r\n') + return fixed + }, [formState.body]) + useEffect(() => { if (!isEditing) { const newCache = _.cloneDeep(formState) @@ -253,11 +266,15 @@ export const ModForm = () => {
{ handleInputChange('body', md) }} + onError={(payload) => { + toast.error('Markdown error. Fix manually in the source mode.') + log(true, LogType.Error, payload.error) + }} />
{typeof formErrors?.body !== 'undefined' && (