5htp-core 0.4.8 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -1
- package/src/client/assets/css/components/table.less +2 -0
- package/src/client/components/Form.ts +1 -1
- package/src/client/components/button.tsx +2 -1
- package/src/client/components/containers/Popover/index.tsx +2 -2
- package/src/client/components/dropdown/index.tsx +16 -6
- package/src/client/components/input/Slider/index.tsx +0 -2
- package/src/client/components/inputv3/Rte/Editor.tsx +271 -0
- package/src/client/components/inputv3/Rte/ToolbarPlugin/BlockFormat.tsx +220 -0
- package/src/client/components/inputv3/Rte/ToolbarPlugin/ElementFormat.tsx +107 -0
- package/src/client/components/inputv3/Rte/ToolbarPlugin/index.tsx +768 -0
- package/src/client/components/inputv3/Rte/appSettings.ts +36 -0
- package/src/client/components/inputv3/Rte/context/FlashMessageContext.tsx +68 -0
- package/src/client/components/inputv3/Rte/context/SettingsContext.tsx +71 -0
- package/src/client/components/inputv3/Rte/context/SharedAutocompleteContext.tsx +71 -0
- package/src/client/components/inputv3/Rte/context/SharedHistoryContext.tsx +35 -0
- package/src/client/components/inputv3/Rte/currentEditor.ts +42 -0
- package/src/client/components/inputv3/Rte/hooks/useFlashMessage.tsx +16 -0
- package/src/client/components/inputv3/Rte/hooks/useReport.ts +67 -0
- package/src/client/components/inputv3/Rte/images/emoji/1F600.png +0 -0
- package/src/client/components/inputv3/Rte/images/emoji/1F641.png +0 -0
- package/src/client/components/inputv3/Rte/images/emoji/1F642.png +0 -0
- package/src/client/components/inputv3/Rte/images/emoji/2764.png +0 -0
- package/src/client/components/inputv3/Rte/images/emoji/LICENSE.md +5 -0
- package/src/client/components/inputv3/Rte/images/icons/draggable-block-menu.svg +1 -0
- package/src/client/components/inputv3/Rte/images/icons/prettier-error.svg +1 -0
- package/src/client/components/inputv3/Rte/images/icons/prettier.svg +1 -0
- package/src/client/components/inputv3/Rte/images/image/LICENSE.md +5 -0
- package/src/client/components/inputv3/Rte/images/image-broken.svg +4 -0
- package/src/client/components/inputv3/Rte/images/logo.svg +1 -0
- package/src/client/components/inputv3/Rte/index.tsx +63 -79
- package/src/client/components/inputv3/Rte/nodes/AutocompleteNode.tsx +119 -0
- package/src/client/components/inputv3/Rte/nodes/EmojiNode.tsx +102 -0
- package/src/client/components/inputv3/Rte/nodes/EquationComponent.tsx +141 -0
- package/src/client/components/inputv3/Rte/nodes/EquationNode.tsx +174 -0
- package/src/client/components/inputv3/Rte/nodes/FigmaNode.tsx +135 -0
- package/src/client/components/inputv3/Rte/nodes/ImageComponent.tsx +468 -0
- package/src/client/components/inputv3/Rte/nodes/ImageNode.css +43 -0
- package/src/client/components/inputv3/Rte/nodes/ImageNode.tsx +266 -0
- package/src/client/components/inputv3/Rte/nodes/InlineImageNode/InlineImageComponent.tsx +402 -0
- package/src/client/components/inputv3/Rte/nodes/InlineImageNode/InlineImageNode.css +94 -0
- package/src/client/components/inputv3/Rte/nodes/InlineImageNode/InlineImageNode.tsx +294 -0
- package/src/client/components/inputv3/Rte/nodes/KeywordNode.ts +67 -0
- package/src/client/components/inputv3/Rte/nodes/LayoutContainerNode.ts +137 -0
- package/src/client/components/inputv3/Rte/nodes/LayoutItemNode.ts +71 -0
- package/src/client/components/inputv3/Rte/nodes/MentionNode.ts +130 -0
- package/src/client/components/inputv3/Rte/nodes/PageBreakNode/index.css +62 -0
- package/src/client/components/inputv3/Rte/nodes/PageBreakNode/index.tsx +170 -0
- package/src/client/components/inputv3/Rte/nodes/PlaygroundNodes.ts +76 -0
- package/src/client/components/inputv3/Rte/nodes/PollComponent.tsx +249 -0
- package/src/client/components/inputv3/Rte/nodes/PollNode.css +187 -0
- package/src/client/components/inputv3/Rte/nodes/PollNode.tsx +209 -0
- package/src/client/components/inputv3/Rte/nodes/StickyComponent.tsx +261 -0
- package/src/client/components/inputv3/Rte/nodes/StickyNode.css +37 -0
- package/src/client/components/inputv3/Rte/nodes/StickyNode.tsx +150 -0
- package/src/client/components/inputv3/Rte/nodes/TweetNode.tsx +223 -0
- package/src/client/components/inputv3/Rte/nodes/YouTubeNode.tsx +184 -0
- package/src/client/components/inputv3/Rte/plugins/ActionsPlugin/index.tsx +334 -0
- package/src/client/components/inputv3/Rte/plugins/AutoEmbedPlugin/index.tsx +352 -0
- package/src/client/components/inputv3/Rte/plugins/AutoLinkPlugin/index.tsx +32 -0
- package/src/client/components/inputv3/Rte/plugins/AutocompletePlugin/index.tsx +2529 -0
- package/src/client/components/inputv3/Rte/plugins/CodeActionMenuPlugin/components/CopyButton/index.tsx +70 -0
- package/src/client/components/inputv3/Rte/plugins/CodeActionMenuPlugin/components/PrettierButton/index.css +14 -0
- package/src/client/components/inputv3/Rte/plugins/CodeActionMenuPlugin/components/PrettierButton/index.tsx +156 -0
- package/src/client/components/inputv3/Rte/plugins/CodeActionMenuPlugin/index.css +54 -0
- package/src/client/components/inputv3/Rte/plugins/CodeActionMenuPlugin/index.tsx +190 -0
- package/src/client/components/inputv3/Rte/plugins/CodeActionMenuPlugin/utils.ts +33 -0
- package/src/client/components/inputv3/Rte/plugins/CodeHighlightPlugin/index.ts +21 -0
- package/src/client/components/inputv3/Rte/plugins/CollapsiblePlugin/Collapsible.css +57 -0
- package/src/client/components/inputv3/Rte/plugins/CollapsiblePlugin/CollapsibleContainerNode.ts +168 -0
- package/src/client/components/inputv3/Rte/plugins/CollapsiblePlugin/CollapsibleContentNode.ts +127 -0
- package/src/client/components/inputv3/Rte/plugins/CollapsiblePlugin/CollapsibleTitleNode.ts +152 -0
- package/src/client/components/inputv3/Rte/plugins/CollapsiblePlugin/CollapsibleUtils.ts +17 -0
- package/src/client/components/inputv3/Rte/plugins/CollapsiblePlugin/index.ts +284 -0
- package/src/client/components/inputv3/Rte/plugins/ComponentPickerPlugin/index.tsx +370 -0
- package/src/client/components/inputv3/Rte/plugins/ContextMenuPlugin/index.tsx +270 -0
- package/src/client/components/inputv3/Rte/plugins/DocsPlugin/index.tsx +20 -0
- package/src/client/components/inputv3/Rte/plugins/DragDropPastePlugin/index.ts +51 -0
- package/src/client/components/inputv3/Rte/plugins/DraggableBlockPlugin/index.css +36 -0
- package/src/client/components/inputv3/Rte/plugins/DraggableBlockPlugin/index.tsx +43 -0
- package/src/client/components/inputv3/Rte/plugins/EmojiPickerPlugin/index.tsx +198 -0
- package/src/client/components/inputv3/Rte/plugins/EmojisPlugin/index.ts +75 -0
- package/src/client/components/inputv3/Rte/plugins/EquationsPlugin/index.tsx +82 -0
- package/src/client/components/inputv3/Rte/plugins/FigmaPlugin/index.tsx +40 -0
- package/src/client/components/inputv3/Rte/plugins/FloatingLinkEditorPlugin/index.css +41 -0
- package/src/client/components/inputv3/Rte/plugins/FloatingLinkEditorPlugin/index.tsx +393 -0
- package/src/client/components/inputv3/Rte/plugins/FloatingTextFormatToolbarPlugin/index.css +141 -0
- package/src/client/components/inputv3/Rte/plugins/FloatingTextFormatToolbarPlugin/index.tsx +388 -0
- package/src/client/components/inputv3/Rte/plugins/ImagesPlugin/index.tsx +350 -0
- package/src/client/components/inputv3/Rte/plugins/InlineImagePlugin/index.tsx +336 -0
- package/src/client/components/inputv3/Rte/plugins/KeywordsPlugin/index.ts +56 -0
- package/src/client/components/inputv3/Rte/plugins/LayoutPlugin/InsertLayoutDialog.tsx +58 -0
- package/src/client/components/inputv3/Rte/plugins/LayoutPlugin/LayoutPlugin.tsx +219 -0
- package/src/client/components/inputv3/Rte/plugins/LinkPlugin/index.tsx +34 -0
- package/src/client/components/inputv3/Rte/plugins/ListMaxIndentLevelPlugin/index.ts +85 -0
- package/src/client/components/inputv3/Rte/plugins/MarkdownShortcutPlugin/index.tsx +16 -0
- package/src/client/components/inputv3/Rte/plugins/MarkdownTransformers/index.ts +324 -0
- package/src/client/components/inputv3/Rte/plugins/MaxLengthPlugin/index.tsx +53 -0
- package/src/client/components/inputv3/Rte/plugins/MentionsPlugin/index.tsx +696 -0
- package/src/client/components/inputv3/Rte/plugins/PageBreakPlugin/index.tsx +57 -0
- package/src/client/components/inputv3/Rte/plugins/PasteLogPlugin/index.tsx +54 -0
- package/src/client/components/inputv3/Rte/plugins/PollPlugin/index.tsx +86 -0
- package/src/client/components/inputv3/Rte/plugins/SpeechToTextPlugin/index.ts +125 -0
- package/src/client/components/inputv3/Rte/plugins/StickyPlugin/index.ts +22 -0
- package/src/client/components/inputv3/Rte/plugins/TabFocusPlugin/index.tsx +65 -0
- package/src/client/components/inputv3/Rte/plugins/TableActionMenuPlugin/index.tsx +773 -0
- package/src/client/components/inputv3/Rte/plugins/TableCellResizer/index.css +12 -0
- package/src/client/components/inputv3/Rte/plugins/TableCellResizer/index.tsx +436 -0
- package/src/client/components/inputv3/Rte/plugins/TableHoverActionsPlugin/index.tsx +287 -0
- package/src/client/components/inputv3/Rte/plugins/TableOfContentsPlugin/index.css +95 -0
- package/src/client/components/inputv3/Rte/plugins/TableOfContentsPlugin/index.tsx +197 -0
- package/src/client/components/inputv3/Rte/plugins/TablePlugin.tsx +178 -0
- package/src/client/components/inputv3/Rte/plugins/TestRecorderPlugin/index.tsx +468 -0
- package/src/client/components/inputv3/Rte/plugins/TreeViewPlugin/index.tsx +26 -0
- package/src/client/components/inputv3/Rte/plugins/TwitterPlugin/index.ts +41 -0
- package/src/client/components/inputv3/Rte/plugins/TypingPerfPlugin/index.ts +117 -0
- package/src/client/components/inputv3/Rte/plugins/YouTubePlugin/index.ts +41 -0
- package/src/client/components/inputv3/Rte/shared/canUseDOM.ts +4 -0
- package/src/client/components/inputv3/Rte/shared/caretFromPoint.ts +40 -0
- package/src/client/components/inputv3/Rte/shared/environment.ts +56 -0
- package/src/client/components/inputv3/Rte/shared/invariant.ts +26 -0
- package/src/client/components/inputv3/Rte/shared/normalizeClassNames.ts +21 -0
- package/src/client/components/inputv3/Rte/shared/react-test-utils.ts +18 -0
- package/src/client/components/inputv3/Rte/shared/reactPatches.ts +22 -0
- package/src/client/components/inputv3/Rte/shared/simpleDiffWithCursor.ts +49 -0
- package/src/client/components/inputv3/Rte/shared/useLayoutEffect.ts +19 -0
- package/src/client/components/inputv3/Rte/shared/warnOnlyOnce.ts +20 -0
- package/src/client/components/inputv3/Rte/style.less +30 -60
- package/src/client/components/inputv3/Rte/themes/CommentEditorTheme.css +13 -0
- package/src/client/components/inputv3/Rte/themes/CommentEditorTheme.ts +20 -0
- package/src/client/components/inputv3/Rte/themes/PlaygroundEditorTheme.css +447 -0
- package/src/client/components/inputv3/Rte/themes/PlaygroundEditorTheme.ts +120 -0
- package/src/client/components/inputv3/Rte/themes/StickyEditorTheme.css +13 -0
- package/src/client/components/inputv3/Rte/themes/StickyEditorTheme.ts +20 -0
- package/src/client/components/inputv3/Rte/ui/ColorPicker.css +88 -0
- package/src/client/components/inputv3/Rte/ui/ColorPicker.tsx +365 -0
- package/src/client/components/inputv3/Rte/ui/ContentEditable.css +44 -0
- package/src/client/components/inputv3/Rte/ui/ContentEditable.tsx +36 -0
- package/src/client/components/inputv3/Rte/ui/DropDown.tsx +259 -0
- package/src/client/components/inputv3/Rte/ui/DropdownColorPicker.tsx +41 -0
- package/src/client/components/inputv3/Rte/ui/EquationEditor.css +38 -0
- package/src/client/components/inputv3/Rte/ui/EquationEditor.tsx +56 -0
- package/src/client/components/inputv3/Rte/ui/FileInput.tsx +38 -0
- package/src/client/components/inputv3/Rte/ui/FlashMessage.css +28 -0
- package/src/client/components/inputv3/Rte/ui/FlashMessage.tsx +29 -0
- package/src/client/components/inputv3/Rte/ui/ImageResizer.tsx +316 -0
- package/src/client/components/inputv3/Rte/ui/Input.css +32 -0
- package/src/client/components/inputv3/Rte/ui/KatexRenderer.tsx +54 -0
- package/src/client/components/inputv3/Rte/ui/Switch.tsx +36 -0
- package/src/client/components/inputv3/Rte/utils/docSerialization.ts +77 -0
- package/src/client/components/inputv3/Rte/utils/emoji-list.ts +16615 -0
- package/src/client/components/inputv3/Rte/utils/getDOMRangeRect.ts +27 -0
- package/src/client/components/inputv3/Rte/utils/getSelectedNode.ts +27 -0
- package/src/client/components/inputv3/Rte/utils/guard.ts +10 -0
- package/src/client/components/inputv3/Rte/utils/isMobileWidth.ts +7 -0
- package/src/client/components/inputv3/Rte/utils/joinClasses.ts +13 -0
- package/src/client/components/inputv3/Rte/utils/setFloatingElemPosition.ts +51 -0
- package/src/client/components/inputv3/Rte/utils/setFloatingElemPositionForLinkEditor.ts +46 -0
- package/src/client/components/inputv3/Rte/utils/swipe.ts +127 -0
- package/src/client/components/inputv3/Rte/utils/url.ts +38 -0
- package/src/client/components/inputv3/base.tsx +8 -5
- package/src/client/components/inputv3/file/index.tsx +11 -5
- package/src/common/data/rte/nodes.ts +60 -9
- package/src/common/validation/index.ts +21 -2
- package/src/common/validation/schema.ts +42 -10
- package/src/common/validation/validator.ts +12 -4
- package/src/common/validation/validators.ts +82 -53
- package/src/server/services/router/http/multipart.ts +0 -1
- package/src/server/services/schema/index.ts +24 -2
- package/src/server/services/schema/request.ts +3 -2
- package/src/server/services/schema/rte.ts +110 -0
- package/src/{common/data/rte/index.ts → server/utils/rte.ts} +27 -16
- package/src/client/components/inputv3/Rte/ExampleTheme.tsx +0 -42
- package/src/client/components/inputv3/Rte/ToolbarPlugin.tsx +0 -167
- package/src/client/components/inputv3/Rte/icons/LICENSE.md +0 -5
- package/src/client/components/inputv3/Rte/icons/arrow-clockwise.svg +0 -4
- package/src/client/components/inputv3/Rte/icons/arrow-counterclockwise.svg +0 -4
- package/src/client/components/inputv3/Rte/icons/journal-text.svg +0 -5
- package/src/client/components/inputv3/Rte/icons/justify.svg +0 -3
- package/src/client/components/inputv3/Rte/icons/text-center.svg +0 -3
- package/src/client/components/inputv3/Rte/icons/text-left.svg +0 -3
- package/src/client/components/inputv3/Rte/icons/text-paragraph.svg +0 -3
- package/src/client/components/inputv3/Rte/icons/text-right.svg +0 -3
- package/src/client/components/inputv3/Rte/icons/type-bold.svg +0 -3
- package/src/client/components/inputv3/Rte/icons/type-italic.svg +0 -3
- package/src/client/components/inputv3/Rte/icons/type-strikethrough.svg +0 -3
- package/src/client/components/inputv3/Rte/icons/type-underline.svg +0 -3
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {TextNode} from 'lexical';
|
|
10
|
+
|
|
11
|
+
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
|
|
12
|
+
import {useLexicalTextEntity} from '@lexical/react/useLexicalTextEntity';
|
|
13
|
+
import {useCallback, useEffect} from 'react';
|
|
14
|
+
|
|
15
|
+
import {$createKeywordNode, KeywordNode} from '../../nodes/KeywordNode';
|
|
16
|
+
|
|
17
|
+
const KEYWORDS_REGEX =
|
|
18
|
+
/(^|$|[^A-Za-zªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԧԱ-Ֆՙա-ևא-תװ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠࢢ-ࢬऄ-हऽॐक़-ॡॱ-ॷॹ-ॿঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-ళవ-హఽౘౙౠౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഅ-ഌഎ-ഐഒ-ഺഽൎൠൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏼᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤜᥐ-ᥭᥰ-ᥴᦀ-ᦫᧁ-ᧇᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎↃↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ々〆〱-〵〻〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿌ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚗꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞎꞐ-ꞓꞠ-Ɦꟸ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꪀ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꯀ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ])(congrats|congratulations|gratuluju|gratuluji|gratulujeme|blahopřeju|blahopřeji|blahopřejeme|Til lykke|Tillykke|Glückwunsch|Gratuliere|felicitaciones|enhorabuena|paljon onnea|onnittelut|Félicitations|gratula|gratulálok|gratulálunk|congratulazioni|complimenti|おめでとう|おめでとうございます|축하해|축하해요|gratulerer|Gefeliciteerd|gratulacje|Parabéns|parabéns|felicitações|felicitări|мои поздравления|поздравляем|поздравляю|gratulujem|blahoželám|ยินดีด้วย|ขอแสดงความยินดี|tebrikler|tebrik ederim|恭喜|祝贺你|恭喜你|恭喜|恭喜|baie geluk|veels geluk|অভিনন্দন|Čestitam|Čestitke|Čestitamo|Συγχαρητήρια|Μπράβο|અભિનંદન|badhai|बधाई|अभिनंदन|Честитам|Свака част|hongera|வாழ்த்துகள்|வாழ்த்துக்கள்|అభినందనలు|അഭിനന്ദനങ്ങൾ|Chúc mừng|מזל טוב|mazel tov|mazal tov)(^|$|[^A-Za-zªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԧԱ-Ֆՙա-ևא-תװ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠࢢ-ࢬऄ-हऽॐक़-ॡॱ-ॷॹ-ॿঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-ళవ-హఽౘౙౠౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഅ-ഌഎ-ഐഒ-ഺഽൎൠൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏼᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤜᥐ-ᥭᥰ-ᥴᦀ-ᦫᧁ-ᧇᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎↃↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ々〆〱-〵〻〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿌ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚗꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞎꞐ-ꞓꞠ-Ɦꟸ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꪀ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꯀ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ])/i;
|
|
19
|
+
|
|
20
|
+
export default function KeywordsPlugin(): JSX.Element | null {
|
|
21
|
+
const [editor] = useLexicalComposerContext();
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (!editor.hasNodes([KeywordNode])) {
|
|
25
|
+
throw new Error('KeywordsPlugin: KeywordNode not registered on editor');
|
|
26
|
+
}
|
|
27
|
+
}, [editor]);
|
|
28
|
+
|
|
29
|
+
const $createKeywordNode_ = useCallback((textNode: TextNode): KeywordNode => {
|
|
30
|
+
return $createKeywordNode(textNode.getTextContent());
|
|
31
|
+
}, []);
|
|
32
|
+
|
|
33
|
+
const getKeywordMatch = useCallback((text: string) => {
|
|
34
|
+
const matchArr = KEYWORDS_REGEX.exec(text);
|
|
35
|
+
|
|
36
|
+
if (matchArr === null) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const hashtagLength = matchArr[2].length;
|
|
41
|
+
const startOffset = matchArr.index + matchArr[1].length;
|
|
42
|
+
const endOffset = startOffset + hashtagLength;
|
|
43
|
+
return {
|
|
44
|
+
end: endOffset,
|
|
45
|
+
start: startOffset,
|
|
46
|
+
};
|
|
47
|
+
}, []);
|
|
48
|
+
|
|
49
|
+
useLexicalTextEntity<KeywordNode>(
|
|
50
|
+
getKeywordMatch,
|
|
51
|
+
KeywordNode,
|
|
52
|
+
$createKeywordNode_,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
import { LexicalEditor } from 'lexical';
|
|
9
|
+
import * as React from 'react';
|
|
10
|
+
import { useState } from 'react';
|
|
11
|
+
|
|
12
|
+
import DropDown, { DropDownItem } from '../../ui/DropDown';
|
|
13
|
+
import { INSERT_LAYOUT_COMMAND } from './LayoutPlugin';
|
|
14
|
+
|
|
15
|
+
// Core
|
|
16
|
+
import Button from '@client/components/button';
|
|
17
|
+
|
|
18
|
+
const LAYOUTS = [
|
|
19
|
+
{ label: '2 columns (equal width)', value: '1fr 1fr' },
|
|
20
|
+
{ label: '2 columns (25% - 75%)', value: '1fr 3fr' },
|
|
21
|
+
{ label: '3 columns (equal width)', value: '1fr 1fr 1fr' },
|
|
22
|
+
{ label: '3 columns (25% - 50% - 25%)', value: '1fr 2fr 1fr' },
|
|
23
|
+
{ label: '4 columns (equal width)', value: '1fr 1fr 1fr 1fr' },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export default function InsertLayoutDialog({
|
|
27
|
+
editor,
|
|
28
|
+
close,
|
|
29
|
+
}: {
|
|
30
|
+
editor: LexicalEditor;
|
|
31
|
+
close: () => void;
|
|
32
|
+
}): React.JSX.Element {
|
|
33
|
+
const [layout, setLayout] = useState(LAYOUTS[0].value);
|
|
34
|
+
const buttonLabel = LAYOUTS.find((item) => item.value === layout)?.label;
|
|
35
|
+
|
|
36
|
+
const onClick = () => {
|
|
37
|
+
editor.dispatchCommand(INSERT_LAYOUT_COMMAND, layout);
|
|
38
|
+
close();
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<>
|
|
43
|
+
<DropDown
|
|
44
|
+
buttonClassName="toolbar-item dialog-dropdown"
|
|
45
|
+
buttonLabel={buttonLabel}>
|
|
46
|
+
{LAYOUTS.map(({ label, value }) => (
|
|
47
|
+
<DropDownItem
|
|
48
|
+
key={value}
|
|
49
|
+
className="item"
|
|
50
|
+
onClick={() => setLayout(value)}>
|
|
51
|
+
<span className="text">{label}</span>
|
|
52
|
+
</DropDownItem>
|
|
53
|
+
))}
|
|
54
|
+
</DropDown>
|
|
55
|
+
<Button type="primary" onClick={onClick}>Insert</Button>
|
|
56
|
+
</>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {ElementNode, LexicalCommand, LexicalNode, NodeKey} from 'lexical';
|
|
10
|
+
|
|
11
|
+
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
|
|
12
|
+
import {
|
|
13
|
+
$findMatchingParent,
|
|
14
|
+
$insertNodeToNearestRoot,
|
|
15
|
+
mergeRegister,
|
|
16
|
+
} from '@lexical/utils';
|
|
17
|
+
import {
|
|
18
|
+
$createParagraphNode,
|
|
19
|
+
$getNodeByKey,
|
|
20
|
+
$getSelection,
|
|
21
|
+
$isRangeSelection,
|
|
22
|
+
COMMAND_PRIORITY_EDITOR,
|
|
23
|
+
COMMAND_PRIORITY_LOW,
|
|
24
|
+
createCommand,
|
|
25
|
+
KEY_ARROW_DOWN_COMMAND,
|
|
26
|
+
KEY_ARROW_LEFT_COMMAND,
|
|
27
|
+
KEY_ARROW_RIGHT_COMMAND,
|
|
28
|
+
KEY_ARROW_UP_COMMAND,
|
|
29
|
+
} from 'lexical';
|
|
30
|
+
import {useEffect} from 'react';
|
|
31
|
+
|
|
32
|
+
import {
|
|
33
|
+
$createLayoutContainerNode,
|
|
34
|
+
$isLayoutContainerNode,
|
|
35
|
+
LayoutContainerNode,
|
|
36
|
+
} from '../../nodes/LayoutContainerNode';
|
|
37
|
+
import {
|
|
38
|
+
$createLayoutItemNode,
|
|
39
|
+
$isLayoutItemNode,
|
|
40
|
+
LayoutItemNode,
|
|
41
|
+
} from '../../nodes/LayoutItemNode';
|
|
42
|
+
|
|
43
|
+
export const INSERT_LAYOUT_COMMAND: LexicalCommand<string> =
|
|
44
|
+
createCommand<string>();
|
|
45
|
+
|
|
46
|
+
export const UPDATE_LAYOUT_COMMAND: LexicalCommand<{
|
|
47
|
+
template: string;
|
|
48
|
+
nodeKey: NodeKey;
|
|
49
|
+
}> = createCommand<{template: string; nodeKey: NodeKey}>();
|
|
50
|
+
|
|
51
|
+
export function LayoutPlugin(): null {
|
|
52
|
+
const [editor] = useLexicalComposerContext();
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (!editor.hasNodes([LayoutContainerNode, LayoutItemNode])) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
'LayoutPlugin: LayoutContainerNode, or LayoutItemNode not registered on editor',
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const $onEscape = (before: boolean) => {
|
|
61
|
+
const selection = $getSelection();
|
|
62
|
+
if (
|
|
63
|
+
$isRangeSelection(selection) &&
|
|
64
|
+
selection.isCollapsed() &&
|
|
65
|
+
selection.anchor.offset === 0
|
|
66
|
+
) {
|
|
67
|
+
const container = $findMatchingParent(
|
|
68
|
+
selection.anchor.getNode(),
|
|
69
|
+
$isLayoutContainerNode,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
if ($isLayoutContainerNode(container)) {
|
|
73
|
+
const parent = container.getParent<ElementNode>();
|
|
74
|
+
const child =
|
|
75
|
+
parent &&
|
|
76
|
+
(before
|
|
77
|
+
? parent.getFirstChild<LexicalNode>()
|
|
78
|
+
: parent?.getLastChild<LexicalNode>());
|
|
79
|
+
const descendant = before
|
|
80
|
+
? container.getFirstDescendant<LexicalNode>()?.getKey()
|
|
81
|
+
: container.getLastDescendant<LexicalNode>()?.getKey();
|
|
82
|
+
|
|
83
|
+
if (
|
|
84
|
+
parent !== null &&
|
|
85
|
+
child === container &&
|
|
86
|
+
selection.anchor.key === descendant
|
|
87
|
+
) {
|
|
88
|
+
if (before) {
|
|
89
|
+
container.insertBefore($createParagraphNode());
|
|
90
|
+
} else {
|
|
91
|
+
container.insertAfter($createParagraphNode());
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return false;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return mergeRegister(
|
|
101
|
+
// When layout is the last child pressing down/right arrow will insert paragraph
|
|
102
|
+
// below it to allow adding more content. It's similar what $insertBlockNode
|
|
103
|
+
// (mainly for decorators), except it'll always be possible to continue adding
|
|
104
|
+
// new content even if trailing paragraph is accidentally deleted
|
|
105
|
+
editor.registerCommand(
|
|
106
|
+
KEY_ARROW_DOWN_COMMAND,
|
|
107
|
+
() => $onEscape(false),
|
|
108
|
+
COMMAND_PRIORITY_LOW,
|
|
109
|
+
),
|
|
110
|
+
editor.registerCommand(
|
|
111
|
+
KEY_ARROW_RIGHT_COMMAND,
|
|
112
|
+
() => $onEscape(false),
|
|
113
|
+
COMMAND_PRIORITY_LOW,
|
|
114
|
+
),
|
|
115
|
+
// When layout is the first child pressing up/left arrow will insert paragraph
|
|
116
|
+
// above it to allow adding more content. It's similar what $insertBlockNode
|
|
117
|
+
// (mainly for decorators), except it'll always be possible to continue adding
|
|
118
|
+
// new content even if leading paragraph is accidentally deleted
|
|
119
|
+
editor.registerCommand(
|
|
120
|
+
KEY_ARROW_UP_COMMAND,
|
|
121
|
+
() => $onEscape(true),
|
|
122
|
+
COMMAND_PRIORITY_LOW,
|
|
123
|
+
),
|
|
124
|
+
editor.registerCommand(
|
|
125
|
+
KEY_ARROW_LEFT_COMMAND,
|
|
126
|
+
() => $onEscape(true),
|
|
127
|
+
COMMAND_PRIORITY_LOW,
|
|
128
|
+
),
|
|
129
|
+
editor.registerCommand(
|
|
130
|
+
INSERT_LAYOUT_COMMAND,
|
|
131
|
+
(template) => {
|
|
132
|
+
editor.update(() => {
|
|
133
|
+
const container = $createLayoutContainerNode(template);
|
|
134
|
+
const itemsCount = getItemsCountFromTemplate(template);
|
|
135
|
+
|
|
136
|
+
for (let i = 0; i < itemsCount; i++) {
|
|
137
|
+
container.append(
|
|
138
|
+
$createLayoutItemNode().append($createParagraphNode()),
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
$insertNodeToNearestRoot(container);
|
|
143
|
+
container.selectStart();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
return true;
|
|
147
|
+
},
|
|
148
|
+
COMMAND_PRIORITY_EDITOR,
|
|
149
|
+
),
|
|
150
|
+
editor.registerCommand(
|
|
151
|
+
UPDATE_LAYOUT_COMMAND,
|
|
152
|
+
({template, nodeKey}) => {
|
|
153
|
+
editor.update(() => {
|
|
154
|
+
const container = $getNodeByKey<LexicalNode>(nodeKey);
|
|
155
|
+
|
|
156
|
+
if (!$isLayoutContainerNode(container)) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const itemsCount = getItemsCountFromTemplate(template);
|
|
161
|
+
const prevItemsCount = getItemsCountFromTemplate(
|
|
162
|
+
container.getTemplateColumns(),
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
// Add or remove extra columns if new template does not match existing one
|
|
166
|
+
if (itemsCount > prevItemsCount) {
|
|
167
|
+
for (let i = prevItemsCount; i < itemsCount; i++) {
|
|
168
|
+
container.append(
|
|
169
|
+
$createLayoutItemNode().append($createParagraphNode()),
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
} else if (itemsCount < prevItemsCount) {
|
|
173
|
+
for (let i = prevItemsCount - 1; i >= itemsCount; i--) {
|
|
174
|
+
const layoutItem = container.getChildAtIndex<LexicalNode>(i);
|
|
175
|
+
|
|
176
|
+
if ($isLayoutItemNode(layoutItem)) {
|
|
177
|
+
layoutItem.remove();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
container.setTemplateColumns(template);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
return true;
|
|
186
|
+
},
|
|
187
|
+
COMMAND_PRIORITY_EDITOR,
|
|
188
|
+
),
|
|
189
|
+
// Structure enforcing transformers for each node type. In case nesting structure is not
|
|
190
|
+
// "Container > Item" it'll unwrap nodes and convert it back
|
|
191
|
+
// to regular content.
|
|
192
|
+
editor.registerNodeTransform(LayoutItemNode, (node) => {
|
|
193
|
+
const parent = node.getParent<ElementNode>();
|
|
194
|
+
if (!$isLayoutContainerNode(parent)) {
|
|
195
|
+
const children = node.getChildren<LexicalNode>();
|
|
196
|
+
for (const child of children) {
|
|
197
|
+
node.insertBefore(child);
|
|
198
|
+
}
|
|
199
|
+
node.remove();
|
|
200
|
+
}
|
|
201
|
+
}),
|
|
202
|
+
editor.registerNodeTransform(LayoutContainerNode, (node) => {
|
|
203
|
+
const children = node.getChildren<LexicalNode>();
|
|
204
|
+
if (!children.every($isLayoutItemNode)) {
|
|
205
|
+
for (const child of children) {
|
|
206
|
+
node.insertBefore(child);
|
|
207
|
+
}
|
|
208
|
+
node.remove();
|
|
209
|
+
}
|
|
210
|
+
}),
|
|
211
|
+
);
|
|
212
|
+
}, [editor]);
|
|
213
|
+
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function getItemsCountFromTemplate(template: string): number {
|
|
218
|
+
return template.trim().split(/\s+/).length;
|
|
219
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {LinkPlugin as LexicalLinkPlugin} from '@lexical/react/LexicalLinkPlugin';
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
|
|
12
|
+
import {validateUrl} from '../../utils/url';
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
hasLinkAttributes?: boolean;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default function LinkPlugin({
|
|
19
|
+
hasLinkAttributes = false,
|
|
20
|
+
}: Props): JSX.Element {
|
|
21
|
+
return (
|
|
22
|
+
<LexicalLinkPlugin
|
|
23
|
+
validateUrl={validateUrl}
|
|
24
|
+
attributes={
|
|
25
|
+
hasLinkAttributes
|
|
26
|
+
? {
|
|
27
|
+
rel: 'noopener noreferrer',
|
|
28
|
+
target: '_blank',
|
|
29
|
+
}
|
|
30
|
+
: undefined
|
|
31
|
+
}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {ElementNode, RangeSelection} from 'lexical';
|
|
10
|
+
|
|
11
|
+
import {$getListDepth, $isListItemNode, $isListNode} from '@lexical/list';
|
|
12
|
+
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
|
|
13
|
+
import {
|
|
14
|
+
$getSelection,
|
|
15
|
+
$isElementNode,
|
|
16
|
+
$isRangeSelection,
|
|
17
|
+
COMMAND_PRIORITY_CRITICAL,
|
|
18
|
+
INDENT_CONTENT_COMMAND,
|
|
19
|
+
} from 'lexical';
|
|
20
|
+
import {useEffect} from 'react';
|
|
21
|
+
|
|
22
|
+
function getElementNodesInSelection(
|
|
23
|
+
selection: RangeSelection,
|
|
24
|
+
): Set<ElementNode> {
|
|
25
|
+
const nodesInSelection = selection.getNodes();
|
|
26
|
+
|
|
27
|
+
if (nodesInSelection.length === 0) {
|
|
28
|
+
return new Set([
|
|
29
|
+
selection.anchor.getNode().getParentOrThrow(),
|
|
30
|
+
selection.focus.getNode().getParentOrThrow(),
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return new Set(
|
|
35
|
+
nodesInSelection.map((n) => ($isElementNode(n) ? n : n.getParentOrThrow())),
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function $shouldPreventIndent(maxDepth: number): boolean {
|
|
40
|
+
const selection = $getSelection();
|
|
41
|
+
|
|
42
|
+
if (!$isRangeSelection(selection)) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const elementNodesInSelection: Set<ElementNode> =
|
|
47
|
+
getElementNodesInSelection(selection);
|
|
48
|
+
|
|
49
|
+
let totalDepth = 0;
|
|
50
|
+
|
|
51
|
+
for (const elementNode of elementNodesInSelection) {
|
|
52
|
+
if ($isListNode(elementNode)) {
|
|
53
|
+
totalDepth = Math.max($getListDepth(elementNode) + 1, totalDepth);
|
|
54
|
+
} else if ($isListItemNode(elementNode)) {
|
|
55
|
+
const parent = elementNode.getParent();
|
|
56
|
+
|
|
57
|
+
if (!$isListNode(parent)) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
'ListMaxIndentLevelPlugin: A ListItemNode must have a ListNode for a parent.',
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
totalDepth = Math.max($getListDepth(parent) + 1, totalDepth);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return totalDepth > maxDepth;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default function ListMaxIndentLevelPlugin({
|
|
71
|
+
maxDepth = 7,
|
|
72
|
+
}: {
|
|
73
|
+
maxDepth?: number;
|
|
74
|
+
}): null {
|
|
75
|
+
const [editor] = useLexicalComposerContext();
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
return editor.registerCommand(
|
|
79
|
+
INDENT_CONTENT_COMMAND,
|
|
80
|
+
() => $shouldPreventIndent(maxDepth),
|
|
81
|
+
COMMAND_PRIORITY_CRITICAL,
|
|
82
|
+
);
|
|
83
|
+
}, [editor, maxDepth]);
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {MarkdownShortcutPlugin} from '@lexical/react/LexicalMarkdownShortcutPlugin';
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
|
|
12
|
+
import {PLAYGROUND_TRANSFORMERS} from '../MarkdownTransformers';
|
|
13
|
+
|
|
14
|
+
export default function MarkdownPlugin(): JSX.Element {
|
|
15
|
+
return <MarkdownShortcutPlugin transformers={PLAYGROUND_TRANSFORMERS} />;
|
|
16
|
+
}
|