diff --git a/app/soapbox/features/compose/editor/index.tsx b/app/soapbox/features/compose/editor/index.tsx index 820f9f101..4949d977e 100644 --- a/app/soapbox/features/compose/editor/index.tsx +++ b/app/soapbox/features/compose/editor/index.tsx @@ -6,7 +6,7 @@ Copyright (c) Meta Platforms, Inc. and affiliates. This source code is licensed under the MIT license found in the LICENSE file in the /app/soapbox/features/compose/editor directory. */ -import { $convertFromMarkdownString, $convertToMarkdownString, TRANSFORMERS } from '@lexical/markdown'; +import { $convertFromMarkdownString, $convertToMarkdownString } from '@lexical/markdown'; import { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin'; import { LexicalComposer, InitialConfigType } from '@lexical/react/LexicalComposer'; import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'; @@ -32,6 +32,7 @@ import DraggableBlockPlugin from './plugins/draggable-block-plugin'; import FloatingLinkEditorPlugin from './plugins/floating-link-editor-plugin'; import FloatingTextFormatToolbarPlugin from './plugins/floating-text-format-toolbar-plugin'; import { MentionPlugin } from './plugins/mention-plugin'; +import { TO_WYSIWYG_TRANSFORMERS } from './transformers'; const StatePlugin = ({ composeId }: { composeId: string }) => { const dispatch = useAppDispatch(); @@ -108,7 +109,7 @@ const ComposeEditor = React.forwardRef(({ return function() { if (compose.content_type === 'text/markdown') { - $convertFromMarkdownString(compose.text, TRANSFORMERS); + $convertFromMarkdownString(compose.text, TO_WYSIWYG_TRANSFORMERS); } else { const paragraph = $createParagraphNode(); const textNode = $createTextNode(compose.text); @@ -175,7 +176,7 @@ const ComposeEditor = React.forwardRef(({ {autoFocus && } { editor.update(() => { - if (editorStateRef) (editorStateRef as any).current = $convertToMarkdownString(TRANSFORMERS); + if (editorStateRef) (editorStateRef as any).current = $convertToMarkdownString(TO_WYSIWYG_TRANSFORMERS); }); }} /> diff --git a/app/soapbox/features/compose/editor/transformers/index.ts b/app/soapbox/features/compose/editor/transformers/index.ts new file mode 100644 index 000000000..bc8dbee16 --- /dev/null +++ b/app/soapbox/features/compose/editor/transformers/index.ts @@ -0,0 +1,92 @@ +// Adapted from: https://github.com/facebook/lexical/issues/2715#issuecomment-1209090485 + +import { + BOLD_ITALIC_UNDERSCORE, + BOLD_ITALIC_STAR, + BOLD_STAR, + BOLD_UNDERSCORE, + STRIKETHROUGH, + INLINE_CODE, + HEADING, + QUOTE, + ORDERED_LIST, + UNORDERED_LIST, + LINK, + TextMatchTransformer, +} from '@lexical/markdown'; + +const replaceEscapedChars = (text: string): string => { + // convert "\*" to "*", "\_" to "_", "\~" to "~", ... + return text + .replaceAll('\\*', '*') + .replaceAll('\\_', '_') + .replaceAll('\\-', '-') + .replaceAll('\\#', '#') + .replaceAll('\\>', '>') + .replaceAll('\\+', '+') + .replaceAll('\\~', '~'); +}; + +const replaceUnescapedChars = (text: string, regexes: RegExp[]): string => { + // convert "*" to "", "_" to "", "~" to "" (all chars, which are not escaped - means with "\" in front) + for (const regex of regexes) { + text = text.replaceAll(regex, ''); + } + return text; +}; + +const UNESCAPE_ITALIC_UNDERSCORE_IMPORT_REGEX = + /([\_])(? null, + importRegExp: UNESCAPE_ITALIC_UNDERSCORE_IMPORT_REGEX, + regExp: UNESCAPE_ITALIC_UNDERSCORE_REGEX, + replace: (textNode, _) => { + const notEscapedUnderscoreRegex = /(? null, + importRegExp: UNESCAPE_BACKSLASH_IMPORT_REGEX, + regExp: UNESCAPE_BACKSLASH_REGEX, + replace: (textNode, _) => { + if (textNode) { + textNode.setTextContent(replaceEscapedChars(textNode.getTextContent())); + } + }, + trigger: '\\', + type: 'text-match', +}; + +export const TO_WYSIWYG_TRANSFORMERS = [ + UNESCAPE_BACKSLASH, + BOLD_ITALIC_UNDERSCORE, + BOLD_ITALIC_STAR, + BOLD_STAR, + BOLD_UNDERSCORE, + STRIKETHROUGH, + UNESCAPE_ITALIC_UNDERSCORE, + // UNESCAPE_ITALIC_STAR, + INLINE_CODE, + HEADING, + QUOTE, + ORDERED_LIST, + UNORDERED_LIST, + LINK, +]; diff --git a/app/soapbox/features/emoji/mapping.ts b/app/soapbox/features/emoji/mapping.ts index 5259c2dc2..601e30920 100644 --- a/app/soapbox/features/emoji/mapping.ts +++ b/app/soapbox/features/emoji/mapping.ts @@ -1,11 +1,6 @@ import data, { EmojiData } from './data'; const stripLeadingZeros = /^0+/; - -function replaceAll(str: string, find: string, replace: string) { - return str.replace(new RegExp(find, 'g'), replace); -} - interface UnicodeMap { [s: string]: { unified: string @@ -80,7 +75,7 @@ const stripcodes = (unified: string, native: string) => { if (unified.includes('200d') && !(unified in blacklist)) { return stripped; } else { - return replaceAll(stripped, '-fe0f', ''); + return stripped.replaceAll('-fe0f', ''); } };