diff --git a/editors/demo/src/NCBI/NCBI.js b/editors/demo/src/NCBI/NCBI.js index a32df6fabf62c37568affad0c2181c702a0f7b1f..dcae24b1a3f83793c1e9f2f4800cbbd201bc90c0 100644 --- a/editors/demo/src/NCBI/NCBI.js +++ b/editors/demo/src/NCBI/NCBI.js @@ -1,12 +1,19 @@ -import React from 'react'; +import React, { useCallback, useState } from 'react'; import { Wax } from 'wax-prosemirror-core'; import styled from 'styled-components'; -import { NcbiLayout, NcbiMiniLayout } from './layout'; -import { configTitle, configMini } from './config'; +import { NcbiLayout, NcbiMiniLayout, EnterLayout } from './layout'; +import { configTitle, configMini, configEnter } from './config'; const Wrapper = styled.div` + display: flex; + flex-direction: column; + padding-top: 50px; + width: 100%; +`; + +const FirstTwoWrapper = styled.div` display: flex; flex-direction: row; justify-content: center; @@ -28,10 +35,44 @@ const TitleEditor = styled.div` width: 80px; `; +const TitleEditorExport = styled.div` + background: #fff; + height: 20px; + position: relative; + top: 2px; + width: 120px; +`; + +const ThirdEditorWrapper = styled.div` + margin-top: 30px; + display: flex; + flex-direction: row; + justify-content: center; +`; + +const ThirdEditor = styled.div` + display: flex; + flex-direction: column; +`; + +const ContentArea = styled.div` + height: 200px; + border: 1px solid black; + overflow-y: auto; +`; + +let a = ''; + const Ncbi = () => { + const [content, setContent] = useState(''); + + const getContent = source => { + setContent(savedContent => `${savedContent} ${source}`); + }; + return ( - <> - <Wrapper> + <Wrapper> + <FirstTwoWrapper> <FirstEditor> <TitleEditor>Basic Editor</TitleEditor> @@ -51,8 +92,20 @@ const Ncbi = () => { layout={NcbiLayout} /> </SecondEditor> - </Wrapper> - </> + </FirstTwoWrapper> + <ThirdEditorWrapper> + <ThirdEditor> + <TitleEditorExport>Export On Enter</TitleEditorExport> + <ContentArea dangerouslySetInnerHTML={{ __html: content }} /> + <Wax + config={configEnter(getContent)} + autoFocus + layout={EnterLayout} + placeholder="Start Typing and press enter..." + /> + </ThirdEditor> + </ThirdEditorWrapper> + </Wrapper> ); }; diff --git a/editors/demo/src/NCBI/config/configEnter.js b/editors/demo/src/NCBI/config/configEnter.js new file mode 100644 index 0000000000000000000000000000000000000000..2bf14ef69232d33be7016a124206222d0a894957 --- /dev/null +++ b/editors/demo/src/NCBI/config/configEnter.js @@ -0,0 +1,60 @@ +import { DefaultSchema } from 'wax-prosemirror-utilities'; +import { + InlineAnnotationsService, + AnnotationToolGroupService, + ListsService, + ListToolGroupService, + BaseService, + BaseToolGroupService, + LinkService, + EnterService, +} from 'wax-prosemirror-services'; + +import invisibles, { + space, + hardBreak, + paragraph, +} from '@guardian/prosemirror-invisibles'; + +const configEnter = getContent => ({ + MenuService: [ + { + templateArea: 'topBar', + toolGroups: [ + { + name: 'Base', + exclude: ['Save'], + }, + { + name: 'Annotations', + exclude: ['Code', 'StrikeThrough', 'Underline', 'SmallCaps'], + }, + 'Lists', + ], + }, + ], + + RulesService: [], + ShortCutsService: {}, + LinkService: {}, + SchemaService: DefaultSchema, + PmPlugins: [invisibles([hardBreak()])], + EnterService: { + getContentOnEnter: source => { + getContent(source); + }, + }, + + services: [ + new EnterService(), + new InlineAnnotationsService(), + new AnnotationToolGroupService(), + new LinkService(), + new ListToolGroupService(), + new BaseService(), + new ListsService(), + new BaseToolGroupService(), + ], +}); + +export default configEnter; diff --git a/editors/demo/src/NCBI/config/index.js b/editors/demo/src/NCBI/config/index.js index 6a377bf2e541ecb4bbb88eac5d884a46ee2c7a76..6e91882d11b10ace641780a9cc70b47053f9f422 100644 --- a/editors/demo/src/NCBI/config/index.js +++ b/editors/demo/src/NCBI/config/index.js @@ -1,2 +1,3 @@ export { default as configTitle } from './configTitle'; export { default as configMini } from './configMini'; +export { default as configEnter } from './configEnter'; diff --git a/editors/demo/src/NCBI/layout/EnterLayout.js b/editors/demo/src/NCBI/layout/EnterLayout.js new file mode 100644 index 0000000000000000000000000000000000000000..f87166de4b8ca74a43635caeb42206e16b193250 --- /dev/null +++ b/editors/demo/src/NCBI/layout/EnterLayout.js @@ -0,0 +1,90 @@ +import React from 'react'; +import styled, { ThemeProvider } from 'styled-components'; +import { ComponentPlugin } from 'wax-prosemirror-core'; +import { cokoTheme } from '../theme'; +import { grid, th } from '@pubsweet/ui-toolkit'; +import EditorMiniElements from './EditorMiniElements'; + +const Wrapper = styled.div` + background: ${th('colorBackground')}; + border: 1px solid grey; + clear: both; + display: flex; + flex-direction: column; + flex-wrap: wrap; + font-family: ${th('fontInterface')}; + font-size: ${th('fontSizeBase')}; + width: 100%; +`; + +const Main = styled.div` + display: flex; +`; + +const TopMenu = styled.div` + background: #fff; + display: inline-flex; + height: 32px; + margin-right: 1px; + user-select: none; + width: 498px; + z-index: 999; + + > div:not(:last-child) { + border: none; + ${th('colorFurniture')}; + } +`; + +const EditorArea = styled.div` + flex-grow: 1; + max-height: 400px; +`; + +const WaxSurfaceScroll = styled.div` + border: none; + box-sizing: border-box; + display: flex; + overflow-y: auto; + max-height: 400px; + position: relative; + width: 100%; + /* PM styles for main content*/ + + /* stylelint-disable-next-line order/properties-alphabetical-order */ + ${EditorMiniElements} +`; + +const EditorContainer = styled.div` + height: 100%; + width: 100%; + max-height: 400px; + + .ProseMirror { + border-top: none; + line-height: 1.6em; + margin-right: ${grid(1)}; + padding: ${grid(1)}; + } +`; + +const TopBar = ComponentPlugin('topBar'); + +const EnterLayout = ({ editor }) => ( + <ThemeProvider theme={cokoTheme}> + <Wrapper> + <TopMenu> + <TopBar /> + </TopMenu> + <Main> + <EditorArea> + <WaxSurfaceScroll> + <EditorContainer>{editor}</EditorContainer> + </WaxSurfaceScroll> + </EditorArea> + </Main> + </Wrapper> + </ThemeProvider> +); + +export default EnterLayout; diff --git a/editors/demo/src/NCBI/layout/index.js b/editors/demo/src/NCBI/layout/index.js index c9f5d741221039277235f56950368f54fc9bc9de..2b6f6f46ea5d42915ac8dd798173e795fe80a543 100644 --- a/editors/demo/src/NCBI/layout/index.js +++ b/editors/demo/src/NCBI/layout/index.js @@ -1,2 +1,3 @@ export { default as NcbiLayout } from './NcbiLayout'; export { default as NcbiMiniLayout } from './NcbiMiniLayout'; +export { default as EnterLayout } from './EnterLayout'; diff --git a/wax-prosemirror-core/src/WaxView.js b/wax-prosemirror-core/src/WaxView.js index 5457ae9ad907921e594c60767c1a5218eb46f5b0..2053780b23d32b158ff26f1c581608c5a59d1129 100644 --- a/wax-prosemirror-core/src/WaxView.js +++ b/wax-prosemirror-core/src/WaxView.js @@ -6,7 +6,6 @@ import React, { useCallback, useMemo, useEffect, - useState, forwardRef, useImperativeHandle, } from 'react'; @@ -46,7 +45,6 @@ const WaxView = forwardRef((props, ref) => { } = props; const WaxEditorRef = useRef(); - const [mounted, setMounted] = useState(false); const context = useContext(WaxContext); const { createPortal } = useContext(PortalContext); @@ -54,20 +52,12 @@ const WaxView = forwardRef((props, ref) => { const schema = context.app.getSchema(); - if (!mounted) { - context.app.bootServices(); - context.app.getShortCuts(); - } - const setEditorRef = useCallback( - // eslint-disable-next-line consistent-return node => { - if (WaxEditorRef.current) { - // this is where you do cleanup if you have to. the WaxEditorRef.current will - // still point to the old ref, the old node. so you have some time here to - // clean up the unmount if you need to. - } if (node) { + context.app.bootServices(); + context.app.getShortCuts(); + const options = WaxOptions({ ...props, schema, @@ -99,8 +89,6 @@ const WaxView = forwardRef((props, ref) => { }, ); - setMounted(true); - context.updateView( { main: view, @@ -108,14 +96,15 @@ const WaxView = forwardRef((props, ref) => { 'main', ); if (debug) applyDevTools(view); - if (autoFocus) + if (autoFocus && view) setTimeout(() => { - if (view) view.focus(); + view.focus(); }, 1000); return () => view.destroy(); } WaxEditorRef.current = node; + return true; }, [readonly, customValues], ); diff --git a/wax-prosemirror-services/src/EssayService/components/EditorComponent.js b/wax-prosemirror-services/src/EssayService/components/EditorComponent.js index 753a54d147e5ee0c42e532ed0c284a38a6e47c28..e89bc34433f988847bcf92365f760698df456c7f 100644 --- a/wax-prosemirror-services/src/EssayService/components/EditorComponent.js +++ b/wax-prosemirror-services/src/EssayService/components/EditorComponent.js @@ -97,7 +97,7 @@ const EditorComponent = ({ node, view, getPos }) => { doc: node, plugins: finalPlugins, }), - // This is the magic part + dispatchTransaction, disallowedTools: ['Images', 'Lists', 'lift', 'MultipleChoice'], handleDOMEvents: { diff --git a/wax-prosemirror-services/src/EssayService/components/EssayAnswerComponent.js b/wax-prosemirror-services/src/EssayService/components/EssayAnswerComponent.js index 6962786007db6214ddac09a98b51dfc2be68b663..7779917927e4251278eb8cfb1622ce196e33f9f0 100644 --- a/wax-prosemirror-services/src/EssayService/components/EssayAnswerComponent.js +++ b/wax-prosemirror-services/src/EssayService/components/EssayAnswerComponent.js @@ -128,7 +128,7 @@ const EssayAnswerComponent = ({ node, view, getPos }) => { doc: node, plugins: finalPlugins, }), - // This is the magic part + dispatchTransaction, disallowedTools: ['MultipleChoice'], handleDOMEvents: { diff --git a/wax-prosemirror-services/src/EssayService/components/EssayQuestionComponent.js b/wax-prosemirror-services/src/EssayService/components/EssayQuestionComponent.js index 32f7389700001bf56649f788e427212343dd57b6..c4c47c48ccd7a99c84336d5efe3fd39d0f65ed47 100644 --- a/wax-prosemirror-services/src/EssayService/components/EssayQuestionComponent.js +++ b/wax-prosemirror-services/src/EssayService/components/EssayQuestionComponent.js @@ -127,7 +127,7 @@ const EssayQuestionComponent = ({ node, view, getPos }) => { doc: node, plugins: finalPlugins, }), - // This is the magic part + dispatchTransaction, disallowedTools: ['MultipleChoice'], handleDOMEvents: { diff --git a/wax-prosemirror-services/src/FillTheGapQuestionService/components/ContainerEditor.js b/wax-prosemirror-services/src/FillTheGapQuestionService/components/ContainerEditor.js index 27bdb40de01cd3bc9d30f6990d809244e213803e..c14832320f66cc8b5a96a6abf3a110510cb6870a 100644 --- a/wax-prosemirror-services/src/FillTheGapQuestionService/components/ContainerEditor.js +++ b/wax-prosemirror-services/src/FillTheGapQuestionService/components/ContainerEditor.js @@ -78,7 +78,6 @@ const EditorComponent = ({ node, view, getPos }) => { doc: node, plugins: finalPlugins, }), - // This is the magic part dispatchTransaction, disallowedTools: [ 'Images', diff --git a/wax-prosemirror-services/src/FillTheGapQuestionService/components/EditorComponent.js b/wax-prosemirror-services/src/FillTheGapQuestionService/components/EditorComponent.js index 77521c768002fe8065c12f1132b0dce9da14a115..957d773ca8a23085fa5e43ee21f31920d8cc8ff0 100644 --- a/wax-prosemirror-services/src/FillTheGapQuestionService/components/EditorComponent.js +++ b/wax-prosemirror-services/src/FillTheGapQuestionService/components/EditorComponent.js @@ -90,7 +90,7 @@ const EditorComponent = ({ node, view, getPos }) => { doc: node, plugins: finalPlugins, }), - // This is the magic part + dispatchTransaction, disallowedTools: [ 'Images', diff --git a/wax-prosemirror-services/src/FillTheGapQuestionService/components/FillTheGapContainerComponent.js b/wax-prosemirror-services/src/FillTheGapQuestionService/components/FillTheGapContainerComponent.js index acdb1891e804c7c11f1ced0ef166fb5dda2819b9..6a39e42d9a2b72c45431013315a1eefc8b1263ec 100644 --- a/wax-prosemirror-services/src/FillTheGapQuestionService/components/FillTheGapContainerComponent.js +++ b/wax-prosemirror-services/src/FillTheGapQuestionService/components/FillTheGapContainerComponent.js @@ -36,7 +36,7 @@ export default ({ node, view, getPos }) => { <span>Fill The Gap</span> <FillTheGapContainer className="fill-the-gap"> <ContainerEditor getPos={getPos} node={node} view={view} /> - {!(readOnly && !customProps.showFeedBack) && ( + {!(readOnly && customProps && !customProps.showFeedBack) && ( <FeedbackComponent getPos={getPos} node={node} diff --git a/wax-prosemirror-services/src/MatchingService/components/MatchingContainerComponent.js b/wax-prosemirror-services/src/MatchingService/components/MatchingContainerComponent.js index 2099fe9a652ec189c378f5649db4b6a2f0293827..d8fbb4c769b0c0ead57f70e932ba1c08236872ce 100644 --- a/wax-prosemirror-services/src/MatchingService/components/MatchingContainerComponent.js +++ b/wax-prosemirror-services/src/MatchingService/components/MatchingContainerComponent.js @@ -1,6 +1,7 @@ /* eslint-disable react/prop-types */ import React, { useContext } from 'react'; import { WaxContext } from 'wax-prosemirror-core'; +import { Icon } from 'wax-prosemirror-components'; import styled from 'styled-components'; import FeedbackComponent from './FeedbackComponent'; @@ -10,10 +11,38 @@ const MatchingContainer = styled.div` `; const MatchingWrapper = styled.div` + display: flex; + flex-direction: column; margin-bottom: ; margin: 0px 38px 15px 38px; + margin-top: 10px; +`; +const QuestionWrapper = styled.div` + display: flex; + flex-direction: row; +`; +const LeftArea = styled.div` + display: flex; +`; +const RightArea = styled.div` + display: flex; +`; +const CreateOptions = styled.div` + display: flex; margin-top: 10px; + border: 1px solid black; +`; + +const ActionButton = styled.button` + border: none; + background: transparent; + cursor: pointer; +`; + +const StyledIconAction = styled(Icon)` + height: 24px; + width: 24px; `; export default ({ node, view, getPos }) => { @@ -30,10 +59,33 @@ export default ({ node, view, getPos }) => { const readOnly = !isEditable; + const addOption = () => {}; + return ( <MatchingWrapper> <span>Matching</span> <MatchingContainer className="matching"> + <QuestionWrapper> + <LeftArea> + <input type="text"></input> + {!readOnly && ( + <ActionButton + onClick={() => addOption(node.attrs.id)} + type="button" + > + <StyledIconAction name="plusSquare" /> + </ActionButton> + )} + </LeftArea> + <RightArea>Right</RightArea> + </QuestionWrapper> + <QuestionWrapper> + <LeftArea> + <input type="text"></input> + </LeftArea> + <RightArea>Right</RightArea> + </QuestionWrapper> + <CreateOptions>Options</CreateOptions> {!(readOnly && !customProps.showFeedBack) && ( <FeedbackComponent getPos={getPos} diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/components/AnswerComponent.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/components/AnswerComponent.js index a9cc737b28eed559cfad8775c7a3f8357f9c2a5e..1bb5badc9b9cfa8188f764323dd76ae049cc6bfe 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/components/AnswerComponent.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/components/AnswerComponent.js @@ -185,7 +185,7 @@ export default ({ node, view, getPos }) => { <QuestionData> <EditorComponent getPos={getPos} node={node} view={view} /> </QuestionData> - {!(readOnly && !customProps.showFeedBack) && ( + {!(readOnly && customProps && !customProps.showFeedBack) && ( <FeedbackComponent getPos={getPos} node={node} diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/components/AnswerComponent.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/components/AnswerComponent.js index 63acff33a489017d810c9646dcf91b8017c95085..ddc4e4b4bff39d1b96f91034602ce9a78f06f9ee 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/components/AnswerComponent.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/components/AnswerComponent.js @@ -184,7 +184,7 @@ export default ({ node, view, getPos }) => { <QuestionData> <EditorComponent getPos={getPos} node={node} view={view} /> </QuestionData> - {!(readOnly && !customProps.showFeedBack) && ( + {!(readOnly && customProps && !customProps.showFeedBack) && ( <FeedbackComponent getPos={getPos} node={node} diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/components/TrueFalseSwitch.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/components/TrueFalseSwitch.js index 62e5fae01a86882e2581a46bb2b52badcddc59a7..eb604d4f8e07893773428d275d0ffcb14daa184e 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/components/TrueFalseSwitch.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/components/TrueFalseSwitch.js @@ -67,7 +67,7 @@ const TrueFalseSwitch = ({ checked, checkedAnswerMode, }) => { - if (customProps.showFeedBack) { + if (customProps && customProps.showFeedBack) { const correct = node.attrs.correct ? 'TRUE' : 'FALSE'; const answer = node.attrs.answer ? 'TRUE' : 'FALSE'; const isCorrect = node.attrs.correct === node.attrs.answer; diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/components/AnswerComponent.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/components/AnswerComponent.js index 8a097de4801230e198479b5ad2f44e43388fb986..8d86699e386d6defa1322bb5917d9936d48cd541 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/components/AnswerComponent.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/components/AnswerComponent.js @@ -184,7 +184,7 @@ export default ({ node, view, getPos }) => { <QuestionData> <EditorComponent getPos={getPos} node={node} view={view} /> </QuestionData> - {!(readOnly && !customProps.showFeedBack) && ( + {!(readOnly && customProps && !customProps.showFeedBack) && ( <FeedbackComponent getPos={getPos} node={node} diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/AnswerComponent.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/AnswerComponent.js index 14c6c4233005ab3603e7ee3755e54631a8ed3ad9..14ca939d22b26569d94d3d2f75cc22ade0f714aa 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/AnswerComponent.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/AnswerComponent.js @@ -184,7 +184,7 @@ export default ({ node, view, getPos }) => { <QuestionData> <EditorComponent getPos={getPos} node={node} view={view} /> </QuestionData> - {!(readOnly && !customProps.showFeedBack) && ( + {!(readOnly && customProps && !customProps.showFeedBack) && ( <FeedbackComponent getPos={getPos} node={node} diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/EditorComponent.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/EditorComponent.js index d95a0be4778818c1efb61a20443fe995b510d3f8..ccead5ca16dfb2078411a7bcb8927144495967ef 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/EditorComponent.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/EditorComponent.js @@ -108,7 +108,6 @@ const EditorComponent = ({ node, view, getPos }) => { doc: node, plugins: finalPlugins, }), - // This is the magic part dispatchTransaction, disallowedTools: ['Images', 'Lists', 'lift', 'MultipleChoice'], handleDOMEvents: { diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/QuestionEditorComponent.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/QuestionEditorComponent.js index eee47af1e3745b0f02a28f93d86272bd391f2109..6c57c169b1bad3b44afc305416b5a32c37762700 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/QuestionEditorComponent.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/QuestionEditorComponent.js @@ -143,7 +143,6 @@ const QuestionEditorComponent = ({ node, view, getPos }) => { doc: node, plugins: finalPlugins, }), - // This is the magic part dispatchTransaction, disallowedTools: ['MultipleChoice'], handleDOMEvents: { diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/YesNoSwitch.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/YesNoSwitch.js index 020056983c1288a48896b7ebd268c89973fc509f..b68f967f52fafe300ceb267928a490de8d0be46a 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/YesNoSwitch.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/YesNoSwitch.js @@ -48,7 +48,7 @@ const YesNoSwitch = ({ checked, checkedAnswerMode, }) => { - if (customProps.showFeedBack) { + if (customProps && customProps.showFeedBack) { const correct = node.attrs.correct ? 'YES' : 'NO'; const answer = node.attrs.answer ? 'YES' : 'NO'; const isCorrect = node.attrs.correct === node.attrs.answer; diff --git a/wax-prosemirror-services/src/NoteService/Editor.js b/wax-prosemirror-services/src/NoteService/Editor.js index dc30aebcbf221d905a3207ac80c697eebc1a26e8..d6b48f3a129b19b253b185a489b5fa8722a5f687 100644 --- a/wax-prosemirror-services/src/NoteService/Editor.js +++ b/wax-prosemirror-services/src/NoteService/Editor.js @@ -48,7 +48,6 @@ export default ({ node, view }) => { doc: node, plugins: [keymap(createKeyBindings()), ...context.app.getPlugins()], }), - // This is the magic part dispatchTransaction, disallowedTools: ['Tables', 'Images', 'Lists', 'CodeBlock'], handleDOMEvents: {