├── .nvmrc ├── editors └── demo │ ├── src │ ├── NCBI │ │ ├── theme │ │ │ ├── elements │ │ │ │ └── ButtonStyles.js │ │ │ └── index.js │ │ ├── config │ │ │ ├── index.js │ │ │ └── configMini.js │ │ └── layout │ │ │ ├── index.js │ │ │ ├── EditorElements.js │ │ │ └── EditorMiniElements.js │ ├── HHMI │ │ ├── config │ │ │ └── index.js │ │ ├── theme │ │ │ ├── index.js │ │ │ └── elements │ │ │ │ ├── index.js │ │ │ │ └── ButtonStyles.js │ │ └── layout │ │ │ ├── index.js │ │ │ └── EditorElements.js │ ├── OEN │ │ ├── config │ │ │ ├── index.js │ │ │ └── defaultSchema.js │ │ ├── layout │ │ │ ├── index.js │ │ │ └── EditorElements.js │ │ └── theme │ │ │ ├── index.js │ │ │ └── elements │ │ │ ├── index.js │ │ │ └── ButtonStyles.js │ ├── Editoria │ │ ├── theme │ │ │ ├── index.js │ │ │ └── elements │ │ │ │ ├── index.js │ │ │ │ └── ButtonStyles.js │ │ ├── config │ │ │ ├── index.js │ │ │ └── defaultSchema.js │ │ └── layout │ │ │ ├── index.js │ │ │ └── EditorElements.js │ └── index.js │ ├── jsconfig.json │ ├── public │ ├── favicon.ico │ └── manifest.json │ └── .gitignore ├── wax-prosemirror-services ├── src │ ├── TrackChangeService │ │ ├── schema │ │ │ ├── trackChangesNodes │ │ │ │ ├── imageTrackNode.js │ │ │ │ ├── listItemTrackNode.js │ │ │ │ └── bulletListTrackNode.js │ │ │ └── trackChangesMarks │ │ │ │ └── index.js │ │ ├── TrackOptionsToolGroupService │ │ │ ├── TrackOptionsToolGroupService.js │ │ │ └── TrackOptions.js │ │ ├── TrackingAndEditingToolGroupService │ │ │ ├── TrackingAndEditingToolGroupService.js │ │ │ └── TrackingAndEditing.js │ │ ├── TrackCommentOptionsToolGroupService │ │ │ └── TrackCommentOptionsToolGroupService.js │ │ ├── ShowHideTrackChangeService │ │ │ ├── ShowHideTrackChangeService.js │ │ │ └── ShowHideTrackChange.js │ │ ├── AcceptTrackChangeService │ │ │ └── AcceptTrackChangeService.js │ │ ├── EnableTrackChangeService │ │ │ └── EnableTrackChangeService.js │ │ ├── RejectTrackChangeService │ │ │ └── RejectTrackChangeService.js │ │ └── track-changes │ │ │ └── helpers │ │ │ └── removeNode.js │ ├── InlineAnnotations │ │ ├── StrongService │ │ │ ├── strong.css │ │ │ ├── schema │ │ │ │ └── strongMark.js │ │ │ ├── StrongService.js │ │ │ └── Strong.js │ │ ├── SubscriptService │ │ │ ├── subscript.css │ │ │ ├── schema │ │ │ │ └── subscriptMark.js │ │ │ ├── SubscriptService.js │ │ │ └── Subscript.js │ │ ├── SuperscriptService │ │ │ ├── superscript.css │ │ │ ├── schema │ │ │ │ └── superscriptMark.js │ │ │ ├── SuperscriptService.js │ │ │ └── Superscript.js │ │ ├── CodeService │ │ │ ├── schema │ │ │ │ └── codeMark.js │ │ │ ├── CodeService.js │ │ │ └── Code.js │ │ ├── InlineAnnotationsService.js │ │ ├── EmphasisService │ │ │ ├── schema │ │ │ │ └── emphasisMark.js │ │ │ ├── EmphasisService.js │ │ │ └── Emphasis.js │ │ ├── UnderlineService │ │ │ ├── schema │ │ │ │ └── underlineMark.js │ │ │ ├── UnderlineService.js │ │ │ └── Underline.js │ │ ├── AnnotationToolGroupService │ │ │ └── AnnotationToolGroupService.js │ │ ├── SmallCapsService │ │ │ ├── SmallCapsService.js │ │ │ ├── schema │ │ │ │ └── smallcapsMark.js │ │ │ └── SmallCaps.js │ │ ├── StrikeThroughService │ │ │ ├── StrikeThroughService.js │ │ │ ├── schema │ │ │ │ └── strikethroughMark.js │ │ │ └── StrikeThrough.js │ │ └── index.js │ ├── FindAndReplaceService │ │ ├── findAndReplace.css │ │ ├── FindAndReplaceToolGroupService │ │ │ ├── FindAndReplaceToolGroupService.js │ │ │ └── FindAndReplaceTool.js │ │ ├── FindAndReplace.js │ │ └── FindAndReplaceService.js │ ├── ModalService │ │ ├── pmPlugins │ │ │ ├── actions.js │ │ │ └── ModalPlugin.js │ │ ├── ModalComponent.js │ │ └── ModalService.js │ ├── ListsService │ │ ├── BlockQuoteService │ │ │ ├── blockQuote.css │ │ │ ├── schema │ │ │ │ └── blockQuoteNode.js │ │ │ ├── BlockQuoteToolGroupService │ │ │ │ ├── BlockQuoteToolGroupService.js │ │ │ │ └── BlockQuoteTool.js │ │ │ └── BlockQuoteService.js │ │ ├── ListsService.js │ │ ├── ListToolGroupService │ │ │ ├── ListToolGroupService.js │ │ │ └── Lists.js │ │ ├── JoinUpService │ │ │ └── JoinUpService.js │ │ ├── lists.css │ │ ├── ListItemService │ │ │ ├── ListItemService.js │ │ │ └── schema │ │ │ │ └── listItemNode.js │ │ ├── LiftService │ │ │ ├── Lift.js │ │ │ └── LiftService.js │ │ ├── index.js │ │ ├── BulletListService │ │ │ ├── schema │ │ │ │ └── bulletListNode.js │ │ │ └── BulletListService.js │ │ └── OrderedListService │ │ │ └── OrderedListService.js │ ├── ImageService │ │ ├── schema │ │ │ ├── index.js │ │ │ └── figureCaptionNode.js │ │ └── ImageToolGroupService │ │ │ ├── ImageToolGroupService.js │ │ │ └── Images.js │ ├── MathService │ │ ├── schema │ │ │ ├── mathSelectMark.js │ │ │ ├── index.js │ │ │ ├── mathInlineNode.js │ │ │ └── mathDisplayNode.js │ │ ├── InlineInputRule.js │ │ └── BlockInputRule.js │ ├── BaseService │ │ ├── BaseService.js │ │ ├── RedoService │ │ │ ├── RedoService.js │ │ │ └── Redo.js │ │ ├── UndoService │ │ │ ├── UndoService.js │ │ │ └── Undo.js │ │ ├── SaveService │ │ │ ├── SaveService.js │ │ │ └── Save.js │ │ ├── BaseToolGroupService │ │ │ ├── BaseToolGroupService.js │ │ │ └── Base.js │ │ └── index.js │ ├── CommentsService │ │ ├── plugins │ │ │ └── CommentDecorationPluginKey.js │ │ ├── comments.css │ │ └── components │ │ │ └── ui │ │ │ └── trackChanges │ │ │ ├── HideShowTool.js │ │ │ ├── removeNode.js │ │ │ └── TrackChangeEnable.js │ ├── CustomTagService │ │ ├── CustomTagService.js │ │ ├── CustomTagToolGroupService │ │ │ ├── CustomTagBlockToolGroupService │ │ │ │ ├── CustomTagBlockToolGroupService.js │ │ │ │ └── CustomTagBlockToolGroup.js │ │ │ ├── CustomTagInlineToolGroupService │ │ │ │ ├── CustomTagInlineToolGroupService.js │ │ │ │ └── CustomTagInlineToolGroup.js │ │ │ └── CustomTagBlockNewToolGroupService │ │ │ │ ├── CustomTagBlockNewToolGroupService.js │ │ │ │ └── CustomTagBlockNewToolGroup.js │ │ ├── CustomTagBlockService │ │ │ ├── CustomTagBlockService.js │ │ │ └── schema │ │ │ │ └── customBlockNode.js │ │ ├── CustomTagInlineService │ │ │ ├── CustomTagInlineTool.js │ │ │ └── schema │ │ │ │ └── customtagInlineMark.js │ │ ├── CustomTagBlockNewService │ │ │ └── CustomTagBlockNewService.js │ │ └── index.js │ ├── TextBlockLevel │ │ ├── TextBlockLevelService.js │ │ ├── TextToolGroupService │ │ │ ├── TextToolGroupService.js │ │ │ └── Text.js │ │ ├── ParagraphService │ │ │ └── ParagraphService.js │ │ ├── SourceNoteService │ │ │ ├── SourceNoteService.js │ │ │ └── schema │ │ │ │ └── sourceNoteNode.js │ │ ├── ExtractProseService │ │ │ ├── ExtractProseService.js │ │ │ └── schema │ │ │ │ └── extractProseNode.js │ │ ├── ExtractPoetryService │ │ │ ├── ExtractPoetryService.js │ │ │ └── schema │ │ │ │ └── extractPoetryNode.js │ │ ├── ParagraphContinuedService │ │ │ ├── ParagraphContinuedService.js │ │ │ └── schema │ │ │ │ └── paragraphContNode.js │ │ └── index.js │ ├── BottomInfoService │ │ ├── BottomInfoService.js │ │ ├── CounterInfoService │ │ │ ├── CounterInfoService.js │ │ │ └── CounterInfoTool.js │ │ ├── ShortCutsInfoService │ │ │ ├── ShortCutsInfoService.js │ │ │ └── ShortCutsInfoTool.js │ │ ├── InfoToolGroupService │ │ │ ├── EditorInfoToolGroupService.js │ │ │ └── InfoTool.js │ │ └── index.js │ ├── NoteService │ │ ├── NoteToolGroupService │ │ │ ├── NoteToolGroupService.js │ │ │ └── Notes.js │ │ ├── NoteEditor.js │ │ ├── schema │ │ │ └── footNoteNode.js │ │ ├── note.css │ │ ├── components │ │ │ └── NoteNumber.js │ │ └── NoteService.js │ ├── AiService │ │ ├── AiToolGroupService │ │ │ ├── AiToolGroupService.js │ │ │ └── ToggleAi.js │ │ └── ToggleAiTool.js │ ├── OENContainersService │ │ ├── schema │ │ │ ├── index.js │ │ │ ├── OenSectionNode.js │ │ │ ├── OenAsideNode.js │ │ │ └── OenContainerNode.js │ │ ├── OENLeftToolGroupService │ │ │ └── OENLeftToolGroupService.js │ │ ├── OENAsideLongToolGroupService │ │ │ ├── OENAsideLongToolGroupService.js │ │ │ └── OENAsideLongToolGroup.js │ │ ├── OENAsideShortToolGroupService │ │ │ ├── OENAsideShortToolGroupService.js │ │ │ └── OENAsideShortToolGroup.js │ │ └── OENContainersToolGroupService │ │ │ ├── OENContainersToolGroup.js │ │ │ └── OENContainersToolGroupService.js │ ├── DisplayBlockLevel │ │ ├── DisplayToolGroupService │ │ │ └── DisplayToolGroupService.js │ │ ├── DisplayBlockLevelService.js │ │ ├── TitleService │ │ │ ├── schema │ │ │ │ └── titleNode.js │ │ │ └── TitleService.js │ │ ├── SubTitleService │ │ │ ├── SubTitleService.js │ │ │ └── schema │ │ │ │ └── subTitleNode.js │ │ ├── AuthorService │ │ │ ├── AuthorService.js │ │ │ └── schema │ │ │ │ └── authorNode.js │ │ ├── EpigraphProseService │ │ │ ├── EpigraphProseService.js │ │ │ └── schema │ │ │ │ └── epigraphProseNode.js │ │ ├── EpigraphPoetryService │ │ │ ├── EpigraphPoetryService.js │ │ │ └── schema │ │ │ │ └── epigraphPoetryNode.js │ │ └── index.js │ ├── CodeBlockService │ │ ├── CodeBlockToolGroupService │ │ │ ├── CodeBlockToolGroupService.js │ │ │ └── CodeBlock.js │ │ ├── schema │ │ │ └── codeBlockNode.js │ │ ├── CodeBlockService.js │ │ └── CodeBlockTool.js │ ├── FullScreenService │ │ ├── FullScreenToolGroupService │ │ │ ├── FullScreenToolGroupService.js │ │ │ └── FullScreen.js │ │ ├── FullScreenService.js │ │ └── FullScreenTool.js │ ├── WaxToolGroups │ │ ├── DisplayTextToolGroupService │ │ │ └── DisplayTextToolGroupService.js │ │ └── BlockDropDownToolGroupService │ │ │ └── BlockDropDownToolGroupService.js │ ├── TransformService │ │ ├── TransformToolGroupService │ │ │ ├── TransformToolGroupService.js │ │ │ └── TransformToolGroup.js │ │ └── TransformService.js │ ├── EditingSuggestingService │ │ ├── EditingSuggestingService.js │ │ └── EditingSuggesting.js │ ├── HighlightService │ │ ├── TextHighlightToolGroupService │ │ │ ├── TextHighlightToolGroupService.js │ │ │ └── HightlightToolGroup.js │ │ ├── schema │ │ │ └── highlightMark.js │ │ └── HightlightService.js │ ├── EnterService │ │ └── EnterService.js │ ├── SpecialCharactersService │ │ ├── SpecialCharactersToolGroupService │ │ │ ├── SpecialCharactersToolGroupService.js │ │ │ └── SpecialCharacters.js │ │ ├── SpecialCharactersService.js │ │ └── SpecialCharactersTool.js │ ├── ExternalAPIContentService │ │ ├── ExternalAPIContentToolGroupService │ │ │ ├── ExternalAPIContentToolGroupService.js │ │ │ └── ExternalAPIContent.js │ │ ├── externalApiContent.css │ │ └── ExternalAPIContentService.js │ └── LinkService │ │ └── schema │ │ └── linkMark.js └── .gitignore ├── .commitlintrc.js ├── .stylelintrc.js ├── wax-citation-service ├── index.js ├── src │ ├── CitationToolGroupService │ │ ├── CitationToolGroupService.js │ │ └── Citation.js │ └── CitationCalloutNodeView.js ├── .gitignore └── README.md ├── .lintstagedrc.js ├── wax-questions-service ├── index.js ├── src │ ├── FillTheGapQuestionService │ │ ├── components │ │ │ └── GapComponent.js │ │ ├── FillTheGapToolGroupService │ │ │ ├── FillTheGapToolGroupService.js │ │ │ └── FillTheGap.js │ │ ├── fillTheGap.css │ │ ├── CreateGapService │ │ │ └── CreateGapService.js │ │ ├── schema │ │ │ ├── fillTheGapContainerNode.js │ │ │ └── fillTheGapNode.js │ │ └── FillTheGapNodeView.js │ ├── NumericalAnswerService │ │ ├── numericalAnswer.css │ │ └── NumericalAnswerContainerNodeView.js │ ├── QuestionsDropDownToolGroupService │ │ └── QuestionsDropDownToolGroupService.js │ ├── MultipleDropDownService │ │ ├── MultipleDropDownToolGroupService │ │ │ ├── MultipleDropDownToolGroupService.js │ │ │ └── MultipleDropDown.js │ │ ├── schema │ │ │ └── multipleDropDownContainerNode.js │ │ ├── CreateDropDownService │ │ │ └── MultipleDropDownNodeView.js │ │ └── MultipleDropDownContainerNodeView.js │ ├── EssayService │ │ ├── essay.css │ │ ├── schema │ │ │ ├── essayContainerNode.js │ │ │ ├── essayAnswerNode.js │ │ │ ├── essayPromptNode.js │ │ │ └── essayQuestionNode.js │ │ ├── EssayAnswerNodeView.js │ │ ├── components │ │ │ ├── EssayQuestionComponent.js │ │ │ └── EssayPromptComponent.js │ │ ├── EssayPromptNodeView.js │ │ └── EssayQuestionNodeView.js │ ├── MultipleChoiceQuestionService │ │ ├── schema │ │ │ ├── questionNode.js │ │ │ ├── multipleChoiceContainerNode.js │ │ │ └── multipleChoiceNode.js │ │ ├── plugins │ │ │ └── MoveCursorPlugin.js │ │ ├── TrueFalseSingleCorrectQuestionService │ │ │ └── schema │ │ │ │ ├── questionTrueFalseSingleNode.js │ │ │ │ └── trueFalseSingleCorrectContainerNode.js │ │ ├── TrueFalseQuestionService │ │ │ └── schema │ │ │ │ ├── trueFalseContainerNode.js │ │ │ │ ├── questionTrueFalseNode.js │ │ │ │ └── trueFalseNode.js │ │ ├── MultipleChoiceSingleCorrectQuestionService │ │ │ └── schema │ │ │ │ ├── questionSingleNode.js │ │ │ │ └── multipleChoiceSingleCorrectContainerNode.js │ │ ├── components │ │ │ └── QuestionComponent.js │ │ └── QuestionNodeView.js │ └── MatchingService │ │ └── MatchingOptionNodeView.js └── .gitignore ├── .directory ├── wax-prosemirror-core ├── jsconfig.json ├── src │ ├── config │ │ ├── defaultServices │ │ │ ├── LayoutService │ │ │ │ ├── components │ │ │ │ │ ├── LayoutFactory.js │ │ │ │ │ └── componentPlugin.js │ │ │ │ ├── DefaultLayout │ │ │ │ │ └── DefaultLayout.js │ │ │ │ └── LayoutService.js │ │ │ ├── PortalService │ │ │ │ └── Portals.js │ │ │ ├── MenuService │ │ │ │ ├── MenuWrapper.js │ │ │ │ └── MenuCollection.js │ │ │ ├── ShortCutsService │ │ │ │ └── ShortCutsService.js │ │ │ ├── OverlayService │ │ │ │ ├── OverlayService.js │ │ │ │ ├── OverLay.js │ │ │ │ └── OverlayComponent.js │ │ │ └── RulesService │ │ │ │ └── RulesService.js │ │ ├── plugins │ │ │ ├── defaultPlugins.js │ │ │ └── placeholder.js │ │ ├── defaultConfig.js │ │ └── Config.js │ ├── Service.js │ ├── components │ │ ├── icons │ │ │ └── Icon.js │ │ ├── helpers │ │ │ ├── useDebounce.js │ │ │ └── useOnClickOutside.js │ │ ├── ToolGroups.js │ │ └── LeftMenuTitle.js │ ├── PmPlugins.js │ ├── utilities │ │ ├── track-changes │ │ │ └── helpers │ │ │ │ └── removeNode.js │ │ ├── schema │ │ │ └── DefaultSchema.js │ │ └── lib │ │ │ └── Middleware.js │ ├── ApplicationContext.js │ └── StateContext.js ├── .gitignore └── rollup.config.js ├── .prettierrc.js ├── lerna.json ├── docker-compose.deploy.yml ├── wax-table-service ├── index.js ├── src │ ├── TablesService.js │ ├── TableToolGroupService │ │ ├── TableToolGroupService.js │ │ └── Tables.js │ ├── EditTableService │ │ └── EditTableService.js │ └── index.js └── .gitignore ├── jsconfig.json ├── docker-compose.yml ├── .cz-config.js ├── .gitignore ├── .dockerignore ├── .gitlab └── issue_templates │ ├── Feature Request.md │ └── bug-report.md ├── .gitlab-ci.yml ├── README.md └── .eslintrc.js /.nvmrc: -------------------------------------------------------------------------------- 1 | 16.19.1 2 | -------------------------------------------------------------------------------- /editors/demo/src/NCBI/theme/elements/ButtonStyles.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /editors/demo/src/HHMI/config/index.js: -------------------------------------------------------------------------------- 1 | export { default as config } from './config'; 2 | -------------------------------------------------------------------------------- /editors/demo/src/HHMI/theme/index.js: -------------------------------------------------------------------------------- 1 | export { default as cokoTheme } from './theme'; 2 | -------------------------------------------------------------------------------- /editors/demo/src/NCBI/theme/index.js: -------------------------------------------------------------------------------- 1 | export { default as cokoTheme } from './theme'; 2 | -------------------------------------------------------------------------------- /editors/demo/src/OEN/config/index.js: -------------------------------------------------------------------------------- 1 | export { default as config } from './config'; 2 | -------------------------------------------------------------------------------- /editors/demo/src/OEN/layout/index.js: -------------------------------------------------------------------------------- 1 | export { default as OenLayout } from './OenLayout'; 2 | -------------------------------------------------------------------------------- /editors/demo/src/OEN/theme/index.js: -------------------------------------------------------------------------------- 1 | export { default as cokoTheme } from "./theme"; 2 | 3 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/schema/trackChangesNodes/imageTrackNode.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/schema/trackChangesNodes/listItemTrackNode.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.commitlintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | }; 4 | -------------------------------------------------------------------------------- /editors/demo/src/Editoria/theme/index.js: -------------------------------------------------------------------------------- 1 | export { default as cokoTheme } from "./theme"; 2 | 3 | -------------------------------------------------------------------------------- /editors/demo/src/HHMI/layout/index.js: -------------------------------------------------------------------------------- 1 | export { default as HhmiLayout } from './HhmiLayout'; 2 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/schema/trackChangesNodes/bulletListTrackNode.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.stylelintrc.js: -------------------------------------------------------------------------------- 1 | const { stylelint } = require('@coko/lint'); 2 | 3 | module.exports = stylelint; 4 | -------------------------------------------------------------------------------- /wax-citation-service/index.js: -------------------------------------------------------------------------------- 1 | export { default as CitationService } from './src/CitationService'; 2 | -------------------------------------------------------------------------------- /.lintstagedrc.js: -------------------------------------------------------------------------------- 1 | const { lintstaged } = require('@coko/lint'); 2 | 3 | module.exports = lintstaged; 4 | -------------------------------------------------------------------------------- /editors/demo/src/HHMI/theme/elements/index.js: -------------------------------------------------------------------------------- 1 | export { default as ButtonStyles } from "./ButtonStyles"; 2 | -------------------------------------------------------------------------------- /editors/demo/src/OEN/theme/elements/index.js: -------------------------------------------------------------------------------- 1 | export { default as ButtonStyles } from "./ButtonStyles"; 2 | -------------------------------------------------------------------------------- /wax-questions-service/index.js: -------------------------------------------------------------------------------- 1 | export { default as QuestionsService } from './src/QuestionsService'; 2 | -------------------------------------------------------------------------------- /editors/demo/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "experimentalDecorators": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /editors/demo/src/Editoria/theme/elements/index.js: -------------------------------------------------------------------------------- 1 | export { default as ButtonStyles } from "./ButtonStyles"; 2 | -------------------------------------------------------------------------------- /.directory: -------------------------------------------------------------------------------- 1 | [Dolphin] 2 | Timestamp=2019,4,23,18,59,6 3 | Version=3 4 | 5 | [Settings] 6 | HiddenFilesShown=true 7 | -------------------------------------------------------------------------------- /wax-prosemirror-core/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "experimentalDecorators": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /editors/demo/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christos8333/wax-prosemirror/HEAD/editors/demo/public/favicon.ico -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | const { prettier } = require('@coko/lint'); 2 | 3 | prettier.semi = true; 4 | 5 | module.exports = prettier; 6 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "lerna": "2.6.0", 3 | "npmClient": "yarn", 4 | "version": "0.9.101", 5 | "useWorkspaces": true 6 | } 7 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/StrongService/strong.css: -------------------------------------------------------------------------------- 1 | /* strong */ 2 | 3 | strong { 4 | font-weight: bold; 5 | } -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/SubscriptService/subscript.css: -------------------------------------------------------------------------------- 1 | 2 | /* subscript*/ 3 | sub { 4 | line-height: 0; 5 | } -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/SuperscriptService/superscript.css: -------------------------------------------------------------------------------- 1 | /* superscript */ 2 | 3 | sup { 4 | line-height: 0; 5 | } -------------------------------------------------------------------------------- /editors/demo/src/Editoria/config/index.js: -------------------------------------------------------------------------------- 1 | export { default as config } from './config'; 2 | export { default as configMobile } from './configMobile'; 3 | -------------------------------------------------------------------------------- /docker-compose.deploy.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | client: 5 | image: cokoapps/wax-demo:latest 6 | ports: 7 | - ${PORT}:3000 8 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/FindAndReplaceService/findAndReplace.css: -------------------------------------------------------------------------------- 1 | 2 | /* find and Replace */ 3 | span.search-result { 4 | background: #bee594; 5 | } -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ModalService/pmPlugins/actions.js: -------------------------------------------------------------------------------- 1 | export default { 2 | HIDE_OVERLAY: "HIDE_OVERLAY", 3 | SHOW_OVERLAY: "SHOW_OVERLAY" 4 | }; 5 | -------------------------------------------------------------------------------- /wax-table-service/index.js: -------------------------------------------------------------------------------- 1 | export { tableEditing, columnResizing } from './src/tableSrc'; 2 | export { default as TablesService } from './src/TablesService'; 3 | -------------------------------------------------------------------------------- /editors/demo/src/Editoria/layout/index.js: -------------------------------------------------------------------------------- 1 | export { default as EditoriaLayout } from './EditoriaLayout'; 2 | export { default as EditoriaMobileLayout } from './EditoriaMobileLayout'; 3 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Experimental Options */ 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | } 7 | } -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | wax: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile-production 8 | ports: 9 | - ${PORT}:3000 10 | -------------------------------------------------------------------------------- /editors/demo/src/NCBI/config/index.js: -------------------------------------------------------------------------------- 1 | export { default as configTitle } from './configTitle'; 2 | export { default as configMini } from './configMini'; 3 | export { default as configEnter } from './configEnter'; 4 | -------------------------------------------------------------------------------- /editors/demo/src/NCBI/layout/index.js: -------------------------------------------------------------------------------- 1 | export { default as NcbiLayout } from './NcbiLayout'; 2 | export { default as NcbiMiniLayout } from './NcbiMiniLayout'; 3 | export { default as EnterLayout } from './EnterLayout'; 4 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultServices/LayoutService/components/LayoutFactory.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/jsx-props-no-spreading */ 2 | import React from 'react'; 3 | 4 | export default Component => props => Component; 5 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/BlockQuoteService/blockQuote.css: -------------------------------------------------------------------------------- 1 | /* block quote */ 2 | blockquote { 3 | padding-left: 1em; 4 | border-left: 3px solid #eee; 5 | margin-left: 0; 6 | margin-right: 0; 7 | } -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ImageService/schema/index.js: -------------------------------------------------------------------------------- 1 | export { default as imageNode } from './imageNode'; 2 | export { default as figureNode } from './figureNode'; 3 | export { default as figureCaptionNode } from './figureCaptionNode'; 4 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/MathService/schema/mathSelectMark.js: -------------------------------------------------------------------------------- 1 | const mathSelectMark = { 2 | toDOM() { 3 | return ['math-select', 0]; 4 | }, 5 | parseDOM: [{ tag: 'math-select' }], 6 | }; 7 | 8 | export default mathSelectMark; 9 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/MathService/schema/index.js: -------------------------------------------------------------------------------- 1 | export { default as mathInlineNode } from './mathInlineNode'; 2 | export { default as mathDisplayNode } from './mathDisplayNode'; 3 | export { default as mathSelectMark } from './mathSelectMark'; 4 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultServices/LayoutService/DefaultLayout/DefaultLayout.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/prop-types */ 2 | import React from 'react'; 3 | 4 | const DefaultLayout = ({ editor }) => <>{editor}; 5 | 6 | export default DefaultLayout; 7 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BaseService/BaseService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import BaseServices from './index'; 3 | 4 | class BaseService extends Service { 5 | dependencies = BaseServices; 6 | } 7 | 8 | export default BaseService; 9 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CommentsService/plugins/CommentDecorationPluginKey.js: -------------------------------------------------------------------------------- 1 | import { PluginKey } from 'prosemirror-state'; 2 | 3 | const CommentDecorationPluginKey = new PluginKey('commentDecorationPlugin'); 4 | 5 | export default CommentDecorationPluginKey; 6 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/CodeService/schema/codeMark.js: -------------------------------------------------------------------------------- 1 | const codeMark = { 2 | parseDOM: { tag: 'code' }, 3 | toDOM(hook, next) { 4 | hook.value = ['code', 0]; 5 | next(); 6 | }, 7 | }; 8 | 9 | export default codeMark; 10 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CommentsService/comments.css: -------------------------------------------------------------------------------- 1 | /* Comments */ 2 | 3 | span.comment { 4 | border-bottom: 2px solid gold; 5 | border-radius: 3px 3px 0 0; 6 | } 7 | 8 | .active-comment { 9 | background-color: gold; 10 | /* color: black; */ 11 | } -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/CustomTagService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import CustomService from './index'; 3 | 4 | class CustomTagService extends Service { 5 | dependencies = CustomService; 6 | } 7 | 8 | export default CustomTagService; 9 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ModalService/ModalComponent.js: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from "react"; 2 | 3 | export default (Component, plugin) => ({ view }) => ( 4 |
5 | 6 | Overlay Area 7 |
8 | ); 9 | // 10 | -------------------------------------------------------------------------------- /wax-questions-service/src/FillTheGapQuestionService/components/GapComponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import EditorComponent from './EditorComponent'; 3 | 4 | export default ({ node, view, getPos }) => { 5 | return ; 6 | }; 7 | -------------------------------------------------------------------------------- /wax-table-service/src/TablesService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import TablesServices from './index'; 3 | import './table.css'; 4 | 5 | class TablesService extends Service { 6 | dependencies = TablesServices; 7 | } 8 | 9 | export default TablesService; 10 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/TextBlockLevelService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import TextServices from './index'; 3 | 4 | class TextBlockLevelService extends Service { 5 | dependencies = TextServices; 6 | } 7 | 8 | export default TextBlockLevelService; 9 | -------------------------------------------------------------------------------- /.cz-config.js: -------------------------------------------------------------------------------- 1 | const { commitizen } = require('@coko/lint'); 2 | 3 | commitizen.scopes = [ 4 | 'core', 5 | 'components', 6 | 'layouts', 7 | 'plugins', 8 | 'schema', 9 | 'services', 10 | 'utilities', 11 | 'editors', 12 | '*', 13 | ]; 14 | 15 | module.exports = commitizen; 16 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BottomInfoService/BottomInfoService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import BottomInfoServices from './index'; 3 | 4 | class BottomInfoService extends Service { 5 | dependencies = BottomInfoServices; 6 | } 7 | 8 | export default BottomInfoService; 9 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BaseService/RedoService/RedoService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Redo from './Redo'; 3 | 4 | class RedoService extends Service { 5 | register() { 6 | this.container.bind('Redo').to(Redo); 7 | } 8 | } 9 | 10 | export default RedoService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BaseService/UndoService/UndoService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Undo from './Undo'; 3 | 4 | class UndoService extends Service { 5 | register() { 6 | this.container.bind('Undo').to(Undo); 7 | } 8 | } 9 | 10 | export default UndoService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/InlineAnnotationsService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import InlineServices from './index'; 3 | 4 | class InlineAnnotationsService extends Service { 5 | dependencies = InlineServices; 6 | } 7 | 8 | export default InlineAnnotationsService; 9 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/EmphasisService/schema/emphasisMark.js: -------------------------------------------------------------------------------- 1 | const emphasisMark = { 2 | parseDOM: [{ tag: 'i' }, { tag: 'em' }, { style: 'font-style=italic' }], 3 | toDOM(hook, next) { 4 | hook.value = ['em', 0]; 5 | next(); 6 | }, 7 | }; 8 | 9 | export default emphasisMark; 10 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/UnderlineService/schema/underlineMark.js: -------------------------------------------------------------------------------- 1 | const underlineMark = { 2 | parseDOM: [{ tag: 'u' }], 3 | toDOM: (hook, next) => { 4 | // eslint-disable-next-line no-param-reassign 5 | hook.value = ['u']; 6 | next(); 7 | }, 8 | }; 9 | 10 | export default underlineMark; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/BlockQuoteService/schema/blockQuoteNode.js: -------------------------------------------------------------------------------- 1 | const blockQuoteNode = { 2 | content: 'block+', 3 | group: 'block', 4 | defining: true, 5 | parseDOM: [{ tag: 'blockquote' }], 6 | toDOM() { 7 | return ['blockquote', 0]; 8 | }, 9 | }; 10 | 11 | export default blockQuoteNode; 12 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/ListsService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import ListsServices from './index'; 3 | import './lists.css'; 4 | 5 | class ListsService extends Service { 6 | name = 'ListsService'; 7 | dependencies = ListsServices; 8 | } 9 | 10 | export default ListsService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultServices/PortalService/Portals.js: -------------------------------------------------------------------------------- 1 | import { injectable } from 'inversify'; 2 | 3 | @injectable() 4 | export default class Portals { 5 | portals = []; 6 | addPortal(portal) { 7 | this.portals.push(portal); 8 | } 9 | 10 | getPortals() { 11 | return this.portals; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BaseService/SaveService/SaveService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Save from './Save'; 3 | 4 | class SaveService extends Service { 5 | name = 'SaveService'; 6 | register() { 7 | this.container.bind('Save').to(Save); 8 | } 9 | } 10 | 11 | export default SaveService; 12 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/SubscriptService/schema/subscriptMark.js: -------------------------------------------------------------------------------- 1 | const subscriptMark = { 2 | excludes: 'superscript', 3 | parseDOM: [{ tag: 'sub' }, { style: 'vertical-align=sub' }], 4 | toDOM(hook, next) { 5 | hook.value = ['sub']; 6 | next(); 7 | }, 8 | }; 9 | 10 | export default subscriptMark; 11 | -------------------------------------------------------------------------------- /wax-table-service/src/TableToolGroupService/TableToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Tables from './Tables'; 3 | 4 | class TableToolGroupService extends Service { 5 | register() { 6 | this.container.bind('Tables').to(Tables); 7 | } 8 | } 9 | 10 | export default TableToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BaseService/BaseToolGroupService/BaseToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Base from './Base'; 3 | 4 | class BaseToolGroupService extends Service { 5 | register() { 6 | this.container.bind('Base').to(Base); 7 | } 8 | } 9 | 10 | export default BaseToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/plugins/defaultPlugins.js: -------------------------------------------------------------------------------- 1 | import { history } from 'prosemirror-history'; 2 | import { dropCursor } from 'prosemirror-dropcursor'; 3 | import { gapCursor } from 'prosemirror-gapcursor'; 4 | import FakeCursorPlugin from './FakeCursorPlugin'; 5 | 6 | export default [dropCursor(), gapCursor(), history(), FakeCursorPlugin()]; 7 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BottomInfoService/CounterInfoService/CounterInfoService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import CounterInfoTool from './CounterInfoTool'; 3 | 4 | export default class CounterInfoService extends Service { 5 | register() { 6 | this.container.bind('CounterInfoTool').to(CounterInfoTool); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/ListToolGroupService/ListToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Lists from './Lists'; 3 | 4 | class ListToolGroupService extends Service { 5 | register() { 6 | this.container.bind('Lists').to(Lists); 7 | } 8 | } 9 | 10 | export default ListToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/NoteService/NoteToolGroupService/NoteToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Notes from './Notes'; 3 | 4 | class NoteToolGroupService extends Service { 5 | register() { 6 | this.container.bind('Notes').to(Notes); 7 | } 8 | } 9 | 10 | export default NoteToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/TextToolGroupService/TextToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Text from './Text'; 3 | 4 | class TextToolGroupService extends Service { 5 | register() { 6 | this.container.bind('Text').to(Text); 7 | } 8 | } 9 | 10 | export default TextToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultServices/LayoutService/LayoutService.js: -------------------------------------------------------------------------------- 1 | import Service from '../../../Service'; 2 | import Layout from './Layout'; 3 | 4 | export default class LayoutService extends Service { 5 | name = 'LayoutService'; 6 | 7 | register() { 8 | this.container.bind('Layout').to(Layout).inSingletonScope(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/AiService/AiToolGroupService/AiToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import ToggleAi from './ToggleAi'; 3 | 4 | class AiToolGroupService extends Service { 5 | register() { 6 | this.container.bind('ToggleAi').to(ToggleAi); 7 | } 8 | } 9 | 10 | export default AiToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/SuperscriptService/schema/superscriptMark.js: -------------------------------------------------------------------------------- 1 | const superscriptMark = { 2 | excludes: 'subscript', 3 | parseDOM: [{ tag: 'sup' }, { style: 'vertical-align=super' }], 4 | toDOM: (hook, next) => { 5 | hook.value = ['sup']; 6 | next(); 7 | }, 8 | }; 9 | 10 | export default superscriptMark; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/OENContainersService/schema/index.js: -------------------------------------------------------------------------------- 1 | import OenAsideNode from './OenAsideNode'; 2 | import OenContainerNode from './OenContainerNode'; 3 | import OenSectionNode from './OenSectionNode'; 4 | 5 | export default { 6 | oen_container: OenContainerNode, 7 | oen_section: OenSectionNode, 8 | oen_aside: OenAsideNode, 9 | }; 10 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/ParagraphService/ParagraphService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Paragraph from './Paragraph'; 3 | 4 | class ParagraphService extends Service { 5 | register() { 6 | this.container.bind('Paragraph').to(Paragraph); 7 | } 8 | } 9 | 10 | export default ParagraphService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ImageService/ImageToolGroupService/ImageToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Images from './Images'; 3 | 4 | class ImageToolGroupService extends Service { 5 | register() { 6 | this.container.bind('Images').to(Images); 7 | } 8 | } 9 | 10 | export default ImageToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-citation-service/src/CitationToolGroupService/CitationToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Citation from './Citation'; 3 | 4 | class CitationToolGroupService extends Service { 5 | register() { 6 | this.container.bind('Citation').to(Citation); 7 | } 8 | } 9 | 10 | export default CitationToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BottomInfoService/ShortCutsInfoService/ShortCutsInfoService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import ShortCutsInfoTool from './ShortCutsInfoTool'; 3 | 4 | export default class ShortCutsInfoService extends Service { 5 | register() { 6 | this.container.bind('ShortCutsInfoTool').to(ShortCutsInfoTool); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/schema/trackChangesMarks/index.js: -------------------------------------------------------------------------------- 1 | import insertionMark from './insertionMark'; 2 | import deletionMark from './deletionMark'; 3 | import formatChangeMark from './formatChangeMark'; 4 | 5 | export default { 6 | format_change: formatChangeMark, 7 | insertion: insertionMark, 8 | deletion: deletionMark, 9 | }; 10 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/DisplayToolGroupService/DisplayToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Display from './Display'; 3 | 4 | class DisplayToolGroupService extends Service { 5 | register() { 6 | this.container.bind('Display').to(Display); 7 | } 8 | } 9 | 10 | export default DisplayToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/MathService/schema/mathInlineNode.js: -------------------------------------------------------------------------------- 1 | const mathInlineNode = { 2 | group: 'inline math', 3 | content: 'text*', 4 | inline: true, 5 | atom: true, 6 | toDOM: () => ['math-inline', { class: 'math-node' }, 0], 7 | parseDOM: [ 8 | { 9 | tag: 'math-inline', 10 | }, 11 | ], 12 | }; 13 | 14 | export default mathInlineNode; 15 | -------------------------------------------------------------------------------- /wax-table-service/src/EditTableService/EditTableService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import TableDropDownOptions from './TableDropDownOptions'; 3 | 4 | class EditTableService extends Service { 5 | register() { 6 | this.container.bind('TableDropDownOptions').to(TableDropDownOptions); 7 | } 8 | } 9 | 10 | export default EditTableService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/MathService/schema/mathDisplayNode.js: -------------------------------------------------------------------------------- 1 | const mathDisplayNode = { 2 | group: 'block math', 3 | content: 'text*', 4 | atom: true, 5 | code: true, 6 | toDOM: () => ['math-display', { class: 'math-node' }, 0], 7 | parseDOM: [ 8 | { 9 | tag: 'math-display', 10 | }, 11 | ], 12 | }; 13 | 14 | export default mathDisplayNode; 15 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/NoteService/NoteEditor.js: -------------------------------------------------------------------------------- 1 | /* eslint react/prop-types: 0 */ 2 | import React from 'react'; 3 | import Editor from './Editor'; 4 | 5 | export default ({ notes, view }) => { 6 | return ( 7 | <> 8 | {notes.map(note => ( 9 | 10 | ))} 11 | 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/OENContainersService/OENLeftToolGroupService/OENLeftToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import OENTools from './OENTools'; 3 | 4 | class OENLeftToolGroupService extends Service { 5 | register() { 6 | this.container.bind('OENTools').to(OENTools); 7 | } 8 | } 9 | 10 | export default OENLeftToolGroupService; 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules 3 | 4 | # testing 5 | /coverage 6 | 7 | # production 8 | /build 9 | 10 | # misc 11 | .DS_Store 12 | .env.local 13 | .env.development.local 14 | .env.test.local 15 | .env.production.local 16 | 17 | npm-debug.log* 18 | yarn-debug.log* 19 | yarn-error.log* 20 | yarn.lock 21 | package-lock.json 22 | lerna-debug.log 23 | README.md 24 | 25 | .vscode -------------------------------------------------------------------------------- /wax-prosemirror-core/src/Service.js: -------------------------------------------------------------------------------- 1 | export default class Service { 2 | setApp(app) { 3 | this.app = app; 4 | } 5 | 6 | get container() { 7 | return this.app.container; 8 | } 9 | 10 | get config() { 11 | return this.app.config.get(`config.${this.name}`) || this.app.config; 12 | } 13 | 14 | get schema() { 15 | return this.app.getSchema(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultServices/MenuService/MenuWrapper.js: -------------------------------------------------------------------------------- 1 | /* eslint no-underscore-dangle: 0 */ 2 | /* eslint react/prop-types: 0 */ 3 | 4 | import React from 'react'; 5 | import { map } from 'lodash'; 6 | 7 | const MainMenuBar = ({ items = [], view }) => { 8 | return <>{map(items, item => item.renderTools(view))}; 9 | }; 10 | 11 | export default MainMenuBar; 12 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CodeBlockService/CodeBlockToolGroupService/CodeBlockToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import CodeBlock from './CodeBlock'; 3 | 4 | class CodeBlockToolGroupService extends Service { 5 | register() { 6 | this.container.bind('CodeBlock').to(CodeBlock); 7 | } 8 | } 9 | 10 | export default CodeBlockToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/NoteService/NoteToolGroupService/Notes.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class Notes extends ToolGroup { 6 | tools = []; 7 | constructor(@inject('Note') note) { 8 | super(); 9 | this.tools = [note]; 10 | } 11 | } 12 | 13 | export default Notes; 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ImageService/ImageToolGroupService/Images.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class Images extends ToolGroup { 6 | tools = []; 7 | constructor(@inject('Image') image) { 8 | super(); 9 | this.tools = [image]; 10 | } 11 | } 12 | 13 | export default Images; 14 | -------------------------------------------------------------------------------- /wax-table-service/src/index.js: -------------------------------------------------------------------------------- 1 | import InsertTableService from './InsertTableService/InsertTableService'; 2 | import EditTableService from './EditTableService/EditTableService'; 3 | import TableToolGroupService from './TableToolGroupService/TableToolGroupService'; 4 | 5 | export default [ 6 | new InsertTableService(), 7 | new EditTableService(), 8 | new TableToolGroupService(), 9 | ]; 10 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/FullScreenService/FullScreenToolGroupService/FullScreenToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import FullScreen from './FullScreen'; 3 | 4 | class FullScreenToolGroupService extends Service { 5 | register() { 6 | this.container.bind('FullScreen').to(FullScreen); 7 | } 8 | } 9 | 10 | export default FullScreenToolGroupService; 11 | -------------------------------------------------------------------------------- /editors/demo/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/WaxToolGroups/DisplayTextToolGroupService/DisplayTextToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import DisplayText from './DisplayText'; 3 | 4 | class DisplayTextToolGroupService extends Service { 5 | register() { 6 | this.container.bind('DisplayText').to(DisplayText); 7 | } 8 | } 9 | 10 | export default DisplayTextToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-questions-service/src/FillTheGapQuestionService/FillTheGapToolGroupService/FillTheGapToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import FillTheGap from './FillTheGap'; 3 | 4 | class FillTheGapToolGroupService extends Service { 5 | register() { 6 | this.container.bind('FillTheGap').to(FillTheGap); 7 | } 8 | } 9 | 10 | export default FillTheGapToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-core/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # testing 5 | /coverage 6 | 7 | # production 8 | /build 9 | 10 | # dist 11 | /dist 12 | 13 | # misc 14 | .DS_Store 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | .directory 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | yarn.lock 25 | package-lock.json 26 | -------------------------------------------------------------------------------- /wax-prosemirror-services/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # testing 5 | /coverage 6 | 7 | # production 8 | /build 9 | 10 | # dist 11 | /dist 12 | 13 | # misc 14 | .DS_Store 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | .directory 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | yarn.lock 25 | package-lock.json 26 | -------------------------------------------------------------------------------- /wax-citation-service/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # testing 5 | /coverage 6 | 7 | # production 8 | /build 9 | 10 | # dist 11 | /dist 12 | 13 | # misc 14 | .DS_Store 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | .directory 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | yarn.lock 25 | package-lock.json 26 | README.md -------------------------------------------------------------------------------- /wax-table-service/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # testing 5 | /coverage 6 | 7 | # production 8 | /build 9 | 10 | # dist 11 | /dist 12 | 13 | # misc 14 | .DS_Store 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | .directory 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | yarn.lock 25 | package-lock.json 26 | README.md -------------------------------------------------------------------------------- /editors/demo/src/HHMI/theme/elements/ButtonStyles.js: -------------------------------------------------------------------------------- 1 | import styled, { css } from "styled-components"; 2 | 3 | export default css` 4 | background: #fff; 5 | border: none; 6 | font-size: inherit; 7 | cursor: pointer; 8 | border-radius: 0; 9 | padding: 5px 10px; 10 | &:disabled { 11 | color: #ccc; 12 | pointer-events: none; 13 | } 14 | &:hover { 15 | background: #f6f6f6; 16 | } 17 | `; 18 | -------------------------------------------------------------------------------- /editors/demo/src/OEN/theme/elements/ButtonStyles.js: -------------------------------------------------------------------------------- 1 | import styled, { css } from "styled-components"; 2 | 3 | export default css` 4 | background: #fff; 5 | border: none; 6 | font-size: inherit; 7 | cursor: pointer; 8 | border-radius: 0; 9 | padding: 5px 10px; 10 | &:disabled { 11 | color: #ccc; 12 | pointer-events: none; 13 | } 14 | &:hover { 15 | background: #f6f6f6; 16 | } 17 | `; 18 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/DisplayBlockLevelService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import DisplayServices from './index'; 3 | 4 | class DisplayBlockLevelService extends Service { 5 | // register() { 6 | // this.config.pushToArray("services", DisplayServices); 7 | // } 8 | dependencies = DisplayServices; 9 | } 10 | 11 | export default DisplayBlockLevelService; 12 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/TrackOptionsToolGroupService/TrackOptionsToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import TrackOptions from './TrackOptions'; 3 | 4 | class TrackOptionsToolGroupService extends Service { 5 | register() { 6 | this.container.bind('TrackOptions').to(TrackOptions); 7 | } 8 | } 9 | 10 | export default TrackOptionsToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/WaxToolGroups/BlockDropDownToolGroupService/BlockDropDownToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import BlockDropDown from './BlockDropDown'; 3 | 4 | class BlockDropDownToolGroupService extends Service { 5 | register() { 6 | this.container.bind('BlockDropDown').to(BlockDropDown); 7 | } 8 | } 9 | 10 | export default BlockDropDownToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-questions-service/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # testing 5 | /coverage 6 | 7 | # production 8 | /build 9 | 10 | # dist 11 | /dist 12 | 13 | # misc 14 | .DS_Store 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | .directory 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | yarn.lock 25 | package-lock.json 26 | README.md -------------------------------------------------------------------------------- /wax-questions-service/src/FillTheGapQuestionService/fillTheGap.css: -------------------------------------------------------------------------------- 1 | /* fill The Gap */ 2 | 3 | .fill-the-gap { 4 | } 5 | 6 | .ProseMirror .fill-the-gap .ProseMirror { 7 | box-shadow: none; 8 | border-bottom: 3px solid #F5F5F7; 9 | line-height: 2.2; 10 | padding: 25px 10px 20px 10px; 11 | } 12 | 13 | .ProseMirror .fill-the-gap span > .ProseMirror { 14 | box-shadow: none; 15 | line-height: 1.6; 16 | } 17 | -------------------------------------------------------------------------------- /editors/demo/src/Editoria/theme/elements/ButtonStyles.js: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | 3 | export default css` 4 | background: #fff; 5 | border: none; 6 | font-size: inherit; 7 | cursor: pointer; 8 | border-radius: 0; 9 | padding: 5px 10px; 10 | &:disabled { 11 | color: #ccc; 12 | pointer-events: none; 13 | } 14 | &:hover { 15 | background: #f6f6f6; 16 | } 17 | `; 18 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/AiService/AiToolGroupService/ToggleAi.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class ToggleAi extends ToolGroup { 6 | tools = []; 7 | 8 | constructor(@inject('ToggleAiTool') toggleAiTool) { 9 | super(); 10 | this.tools = [toggleAiTool]; 11 | } 12 | } 13 | 14 | export default ToggleAi; 15 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CodeBlockService/CodeBlockToolGroupService/CodeBlock.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class CodeBlock extends ToolGroup { 6 | tools = []; 7 | constructor(@inject('CodeBlockTool') codeblock) { 8 | super(); 9 | this.tools = [codeblock]; 10 | } 11 | } 12 | 13 | export default CodeBlock; 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/BlockQuoteService/BlockQuoteToolGroupService/BlockQuoteToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import BlockQuoteTool from './BlockQuoteTool'; 3 | 4 | class BlockQuoteToolGroupService extends Service { 5 | register() { 6 | this.container.bind('BlockQuoteTool').to(BlockQuoteTool); 7 | } 8 | } 9 | 10 | export default BlockQuoteToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TransformService/TransformToolGroupService/TransformToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import TransformToolGroup from './TransformToolGroup'; 3 | 4 | class TransformToolGroupService extends Service { 5 | register() { 6 | this.container.bind('TransformToolGroup').to(TransformToolGroup); 7 | } 8 | } 9 | 10 | export default TransformToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-questions-service/src/NumericalAnswerService/numericalAnswer.css: -------------------------------------------------------------------------------- 1 | /* fill The Gap */ 2 | 3 | .numerical-answer {} 4 | 5 | .ProseMirror .numerical-answer .ProseMirror { 6 | box-shadow: none; 7 | border-bottom: 3px solid #F5F5F7; 8 | line-height: 2.2; 9 | padding: 25px 10px 20px 10px; 10 | } 11 | 12 | .ProseMirror .numerical-answer span>.ProseMirror { 13 | box-shadow: none; 14 | line-height: 1.6; 15 | } -------------------------------------------------------------------------------- /wax-questions-service/src/FillTheGapQuestionService/FillTheGapToolGroupService/FillTheGap.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class FillTheGap extends ToolGroup { 6 | tools = []; 7 | constructor(@inject('CreateGap') CreateGap) { 8 | super(); 9 | this.tools = [CreateGap]; 10 | } 11 | } 12 | 13 | export default FillTheGap; 14 | -------------------------------------------------------------------------------- /wax-questions-service/src/QuestionsDropDownToolGroupService/QuestionsDropDownToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import QuestionsDropDown from './QuestionsDropDown'; 3 | 4 | class QuestionsDropDownToolGroupService extends Service { 5 | register() { 6 | this.container.bind('QuestionsDropDown').to(QuestionsDropDown); 7 | } 8 | } 9 | 10 | export default QuestionsDropDownToolGroupService; 11 | -------------------------------------------------------------------------------- /editors/demo/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BottomInfoService/InfoToolGroupService/EditorInfoToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import InfoToolGroup from './InfoTool'; 3 | 4 | class EditorInfoToolGroupService extends Service { 5 | name = 'EditorInfoToolGroupService'; 6 | register() { 7 | this.container.bind('InfoToolGroup').to(InfoToolGroup); 8 | } 9 | } 10 | export default EditorInfoToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-citation-service/src/CitationToolGroupService/Citation.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class Citation extends ToolGroup { 6 | tools = []; 7 | constructor(@inject('CitationDropDownOptions') citationDropDownOptions) { 8 | super(); 9 | this.tools = [citationDropDownOptions]; 10 | } 11 | } 12 | 13 | export default Citation; 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BaseService/index.js: -------------------------------------------------------------------------------- 1 | import UndoService from './UndoService/UndoService'; 2 | import RedoService from './RedoService/RedoService'; 3 | import SaveService from './SaveService/SaveService'; 4 | import BaseToolGroupService from './BaseToolGroupService/BaseToolGroupService'; 5 | 6 | export default [ 7 | new UndoService(), 8 | new RedoService(), 9 | new SaveService(), 10 | new BaseToolGroupService(), 11 | ]; 12 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/EditingSuggestingService/EditingSuggestingService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import EditingSuggesting from './EditingSuggesting'; 3 | 4 | class EditingSuggestingService extends Service { 5 | name = 'EditingSuggestingService'; 6 | 7 | register() { 8 | this.container.bind('EditingSuggesting').to(EditingSuggesting); 9 | } 10 | } 11 | export default EditingSuggestingService; 12 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/FullScreenService/FullScreenToolGroupService/FullScreen.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class FullScreen extends ToolGroup { 6 | tools = []; 7 | constructor(@inject('FullScreenTool') fullScreenTool) { 8 | super(); 9 | this.tools = [fullScreenTool]; 10 | } 11 | } 12 | 13 | export default FullScreen; 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/HighlightService/TextHighlightToolGroupService/TextHighlightToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import HighlightToolGroup from './HightlightToolGroup'; 3 | 4 | class TextHighlightToolGroupServices extends Service { 5 | register() { 6 | this.container.bind('HighlightToolGroup').to(HighlightToolGroup); 7 | } 8 | } 9 | 10 | export default TextHighlightToolGroupServices; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ModalService/pmPlugins/ModalPlugin.js: -------------------------------------------------------------------------------- 1 | import { Plugin, PluginKey } from "prosemirror-state"; 2 | import actions from "./actions"; 3 | export default key => 4 | new Plugin({ 5 | key: new PluginKey(key), 6 | state: { 7 | init: function init() { 8 | return { 9 | action: actions.HIDE_OVERLAY 10 | }; 11 | }, 12 | apply: function apply(tr) {} 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BottomInfoService/index.js: -------------------------------------------------------------------------------- 1 | import CounterInfoService from './CounterInfoService/CounterInfoService'; 2 | import ShortCutsInfoService from './ShortCutsInfoService/ShortCutsInfoService'; 3 | import EditorInfoToolGroupService from './InfoToolGroupService/EditorInfoToolGroupService'; 4 | 5 | export default [ 6 | new CounterInfoService(), 7 | new ShortCutsInfoService(), 8 | new EditorInfoToolGroupService(), 9 | ]; 10 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleDropDownService/MultipleDropDownToolGroupService/MultipleDropDownToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import MultipleDropDown from './MultipleDropDown'; 3 | 4 | class MultipleDropDownToolGroupService extends Service { 5 | register() { 6 | this.container.bind('MultipleDropDown').to(MultipleDropDown); 7 | } 8 | } 9 | 10 | export default MultipleDropDownToolGroupService; 11 | -------------------------------------------------------------------------------- /editors/demo/src/OEN/layout/EditorElements.js: -------------------------------------------------------------------------------- 1 | import { css } from 'styled-components'; 2 | import { th } from '@pubsweet/ui-toolkit'; 3 | 4 | /* All styles regarding ProseMirror surface and elements */ 5 | 6 | const fontWriting = css` 7 | color: ${th('colorText')}; 8 | font-family: ${th('fontWriting')}; 9 | font-size: ${th('fontSizeBase')}; 10 | `; 11 | 12 | export default css` 13 | .ProseMirror { 14 | ${fontWriting} 15 | } 16 | `; 17 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/FindAndReplaceService/FindAndReplaceToolGroupService/FindAndReplaceToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import FindAndReplaceTool from './FindAndReplaceTool'; 3 | 4 | class FindAndReplaceToolGroupService extends Service { 5 | register() { 6 | this.container.bind('FindAndReplaceTool').to(FindAndReplaceTool); 7 | } 8 | } 9 | 10 | export default FindAndReplaceToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/AnnotationToolGroupService/AnnotationToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import Annotations from './Annotations'; 3 | 4 | class AnnotationToolGroupService extends Service { 5 | name = 'AnnotationToolGroupService'; 6 | 7 | register() { 8 | this.container.bind('Annotations').to(Annotations); 9 | } 10 | } 11 | 12 | export default AnnotationToolGroupService; 13 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/OENContainersService/OENAsideLongToolGroupService/OENAsideLongToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import OENAsideLongToolGroup from './OENAsideLongToolGroup'; 3 | 4 | class OENAsideLongToolGroupService extends Service { 5 | register() { 6 | this.container.bind('OENAsideLongToolGroup').to(OENAsideLongToolGroup); 7 | } 8 | } 9 | 10 | export default OENAsideLongToolGroupService; 11 | -------------------------------------------------------------------------------- /editors/demo/src/Editoria/layout/EditorElements.js: -------------------------------------------------------------------------------- 1 | import { css } from 'styled-components'; 2 | import { th } from '@pubsweet/ui-toolkit'; 3 | 4 | /* All styles regarding ProseMirror surface and elements */ 5 | 6 | const fontWriting = css` 7 | color: ${th('colorText')}; 8 | font-family: ${th('fontWriting')}; 9 | font-size: ${th('fontSizeBase')}; 10 | `; 11 | 12 | export default css` 13 | .ProseMirror { 14 | ${fontWriting} 15 | } 16 | `; 17 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/EnterService/EnterService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import GetContentOnEnterPlugin from './plugins/GetContentOnEnterPlugin'; 3 | 4 | class EnterService extends Service { 5 | name = 'EnterService'; 6 | 7 | boot() { 8 | this.app.PmPlugins.add( 9 | 'getContentOnEnterPlugin', 10 | GetContentOnEnterPlugin(this.config), 11 | ); 12 | } 13 | } 14 | 15 | export default EnterService; 16 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/OENContainersService/OENAsideShortToolGroupService/OENAsideShortToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import OENAsideShortToolGroup from './OENAsideShortToolGroup'; 3 | 4 | class OENAsideShortToolGroupService extends Service { 5 | register() { 6 | this.container.bind('OENAsideShortToolGroup').to(OENAsideShortToolGroup); 7 | } 8 | } 9 | 10 | export default OENAsideShortToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/SpecialCharactersService/SpecialCharactersToolGroupService/SpecialCharactersToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import SpecialCharacters from './SpecialCharacters'; 3 | 4 | class SpecialCharactersToolGroupService extends Service { 5 | register() { 6 | this.container.bind('SpecialCharacters').to(SpecialCharacters); 7 | } 8 | } 9 | 10 | export default SpecialCharactersToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/TrackingAndEditingToolGroupService/TrackingAndEditingToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import TrackingAndEditing from './TrackingAndEditing'; 3 | 4 | class TrackingAndEditingToolGroupService extends Service { 5 | register() { 6 | this.container.bind('TrackingAndEditing').to(TrackingAndEditing); 7 | } 8 | } 9 | 10 | export default TrackingAndEditingToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-questions-service/src/EssayService/essay.css: -------------------------------------------------------------------------------- 1 | /* -- Essay ---------------------------------- */ 2 | .essay { 3 | border: 3px solid #f5f5f7; 4 | margin-bottom: 30px; 5 | margin-top: 30px; 6 | padding: 3px; 7 | } 8 | 9 | essay::before { 10 | background-color: #fff; 11 | bottom: 22px; 12 | color: #535e76; 13 | content: 'Essay'; 14 | height: 10px; 15 | left: -1px; 16 | position: relative; 17 | width: 30px; 18 | } -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TransformService/TransformToolGroupService/TransformToolGroup.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class TransformToolGroup extends ToolGroup { 6 | tools = []; 7 | 8 | constructor(@inject('TransformTool') transformCase) { 9 | super(); 10 | this.tools = [transformCase]; 11 | } 12 | } 13 | 14 | export default TransformToolGroup; 15 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultServices/MenuService/MenuCollection.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { injectable, multiInject } from 'inversify'; 3 | 4 | @injectable() 5 | class MenuCollection { 6 | menus = []; 7 | constructor(@multiInject('Menu') menus) { 8 | this.menus = menus; 9 | } 10 | 11 | getMenu(name) { 12 | return this.menus.find(menu => menu.name === name); 13 | } 14 | } 15 | 16 | export default MenuCollection; 17 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ExternalAPIContentService/ExternalAPIContentToolGroupService/ExternalAPIContentToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import ExternalAPIContent from './ExternalAPIContent'; 3 | 4 | class ExternalAPIContentToolGroupService extends Service { 5 | register() { 6 | this.container.bind('ExternalAPIContent').to(ExternalAPIContent); 7 | } 8 | } 9 | 10 | export default ExternalAPIContentToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/HighlightService/TextHighlightToolGroupService/HightlightToolGroup.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class HighlightToolGroup extends ToolGroup { 6 | tools = []; 7 | constructor(@inject('TextHighlightTool') texthighlight) { 8 | super(); 9 | this.tools = [texthighlight]; 10 | } 11 | } 12 | 13 | export default HighlightToolGroup; 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/TrackCommentOptionsToolGroupService/TrackCommentOptionsToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import TrackCommentOptions from './TrackCommentOptions'; 3 | 4 | class TrackCommentOptionsToolGroupService extends Service { 5 | register() { 6 | this.container.bind('TrackCommentOptions').to(TrackCommentOptions); 7 | } 8 | } 9 | 10 | export default TrackCommentOptionsToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleDropDownService/MultipleDropDownToolGroupService/MultipleDropDown.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class MultipleDropDown extends ToolGroup { 6 | tools = []; 7 | constructor(@inject('CreateDropDown') CreateDropDown) { 8 | super(); 9 | this.tools = [CreateDropDown]; 10 | } 11 | } 12 | 13 | export default MultipleDropDown; 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BaseService/BaseToolGroupService/Base.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class Base extends ToolGroup { 6 | tools = []; 7 | constructor( 8 | @inject('Undo') undo, 9 | @inject('Redo') redo, 10 | @inject('Save') save, 11 | ) { 12 | super(); 13 | this.tools = [undo, redo, save]; 14 | } 15 | } 16 | 17 | export default Base; 18 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/FindAndReplaceService/FindAndReplaceToolGroupService/FindAndReplaceTool.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class FindAndReplaceTool extends ToolGroup { 6 | tools = []; 7 | constructor(@inject('FindAndReplace') findAndReplace) { 8 | super(); 9 | this.tools = [findAndReplace]; 10 | } 11 | } 12 | 13 | export default FindAndReplaceTool; 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/JoinUpService/JoinUpService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import JoinUp from './JoinUp'; 3 | 4 | class JoinUpService extends Service { 5 | name = 'JoinUpService'; 6 | register() { 7 | // this.container.bind('JoinUp').to(JoinUp); 8 | this.container.bind('JoinUp').toDynamicValue(() => { 9 | return new JoinUp(this.config); 10 | }); 11 | } 12 | } 13 | 14 | export default JoinUpService; 15 | -------------------------------------------------------------------------------- /wax-table-service/src/TableToolGroupService/Tables.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class Tables extends ToolGroup { 6 | tools = []; 7 | constructor( 8 | @inject('Table') table, 9 | @inject('TableDropDownOptions') tableDropDownOptions, 10 | ) { 11 | super(); 12 | this.tools = [table, tableDropDownOptions]; 13 | } 14 | } 15 | 16 | export default Tables; 17 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/lists.css: -------------------------------------------------------------------------------- 1 | /* lists */ 2 | 3 | ul, 4 | ol { 5 | padding-left: 30px; 6 | } 7 | 8 | /* ol { 9 | counter-reset: item 10 | } 11 | 12 | li { 13 | display: block; 14 | margin-top: 1em; 15 | margin-bottom: 1em; 16 | } 17 | 18 | li p { 19 | display: inline; 20 | } 21 | 22 | li:before { 23 | content: counters(item, ".") " "; 24 | counter-increment: item 25 | } */ -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/ShowHideTrackChangeService/ShowHideTrackChangeService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import ShowHideTrackChange from './ShowHideTrackChange'; 3 | 4 | class ShowHideTrackChangeService extends Service { 5 | name = 'ShowHideTrackChangeService'; 6 | 7 | register() { 8 | this.container.bind('ShowHideTrackChange').to(ShowHideTrackChange); 9 | } 10 | } 11 | 12 | export default ShowHideTrackChangeService; 13 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TransformService/TransformService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import TransformTool from './TransformTool'; 3 | import TransformToolGroupService from './TransformToolGroupService/TransformToolGroupService'; 4 | 5 | export default class TransformService extends Service { 6 | register() { 7 | this.container.bind('TransformTool').to(TransformTool); 8 | } 9 | 10 | dependencies = [new TransformToolGroupService()]; 11 | } 12 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/CustomTagToolGroupService/CustomTagBlockToolGroupService/CustomTagBlockToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import CustomTagBlockToolGroup from './CustomTagBlockToolGroup'; 3 | 4 | class CustomTagBlockToolGroupService extends Service { 5 | register() { 6 | this.container.bind('CustomTagBlockToolGroup').to(CustomTagBlockToolGroup); 7 | } 8 | } 9 | 10 | export default CustomTagBlockToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/CustomTagToolGroupService/CustomTagInlineToolGroupService/CustomTagInlineToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import CustomTagInlineToolGroup from './CustomTagInlineToolGroup'; 3 | 4 | class CustomTagInlineToolGroupService extends Service { 5 | register() { 6 | this.container.bind('CustomTagInline').to(CustomTagInlineToolGroup); 7 | } 8 | } 9 | 10 | export default CustomTagInlineToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/ListItemService/ListItemService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import listItemNode from './schema/listItemNode'; 3 | 4 | class ListItemService extends Service { 5 | register() { 6 | const createNode = this.container.get('CreateNode'); 7 | createNode( 8 | { 9 | list_item: listItemNode, 10 | }, 11 | { toWaxSchema: true }, 12 | ); 13 | } 14 | } 15 | 16 | export default ListItemService; 17 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/SpecialCharactersService/SpecialCharactersToolGroupService/SpecialCharacters.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class SpecialCharacters extends ToolGroup { 6 | tools = []; 7 | constructor(@inject('SpecialCharactersTool') specialCharactersTool) { 8 | super(); 9 | this.tools = [specialCharactersTool]; 10 | } 11 | } 12 | 13 | export default SpecialCharacters; 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/CustomTagToolGroupService/CustomTagBlockNewToolGroupService/CustomTagBlockNewToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import CustomTagBlockNewToolGroup from './CustomTagBlockNewToolGroup'; 3 | 4 | class CustomTagBlockNewToolGroupService extends Service { 5 | register() { 6 | this.container.bind('CustomTagBlock').to(CustomTagBlockNewToolGroup); 7 | } 8 | } 9 | 10 | export default CustomTagBlockNewToolGroupService; 11 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ExternalAPIContentService/ExternalAPIContentToolGroupService/ExternalAPIContent.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class ExternalAPIContent extends ToolGroup { 6 | tools = []; 7 | constructor(@inject('ExternalAPIContentTool') ExternalAPIContentTool) { 8 | super(); 9 | this.tools = [ExternalAPIContentTool]; 10 | } 11 | } 12 | 13 | export default ExternalAPIContent; 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/BlockQuoteService/BlockQuoteToolGroupService/BlockQuoteTool.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class BlockQuoteTool extends ToolGroup { 6 | tools = []; 7 | title = ''; 8 | 9 | constructor(@inject('BlockQuote') blockQuote, @inject('Lift') lift) { 10 | super(); 11 | this.tools = [blockQuote, lift]; 12 | } 13 | } 14 | 15 | export default BlockQuoteTool; 16 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/components/icons/Icon.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import icons from './icons'; 5 | 6 | /** 7 | * Only works with SVG icons from icons.js 8 | */ 9 | 10 | const SVGIcon = props => { 11 | const { className, name } = props; 12 | const Component = icons[name]; 13 | return ; 14 | }; 15 | 16 | SVGIcon.propTypes = { 17 | name: PropTypes.string.isRequired, 18 | }; 19 | 20 | export default SVGIcon; 21 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/components/helpers/useDebounce.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | 3 | const useDebounce = (value, delay) => { 4 | const [debouncedValue, setDebouncedValue] = useState(value); 5 | 6 | useEffect(() => { 7 | const handler = setTimeout(() => { 8 | setDebouncedValue(value); 9 | }, delay); 10 | 11 | return () => { 12 | clearTimeout(handler); 13 | }; 14 | }, [value]); 15 | 16 | return debouncedValue; 17 | }; 18 | 19 | export default useDebounce; 20 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/CustomTagToolGroupService/CustomTagInlineToolGroupService/CustomTagInlineToolGroup.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class CustomTagInlineToolGroup extends ToolGroup { 6 | tools = []; 7 | 8 | constructor(@inject('CustomTagInlineTool') customTagInline) { 9 | super(); 10 | this.tools = [customTagInline]; 11 | } 12 | } 13 | 14 | export default CustomTagInlineToolGroup; 15 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/AcceptTrackChangeService/AcceptTrackChangeService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import AcceptTrackChange from './AcceptTrackChange'; 3 | 4 | class AcceptTrackChangeService extends Service { 5 | name = 'AcceptTrackChangeService'; 6 | register() { 7 | this.container.bind('AcceptTrackChange').toDynamicValue(() => { 8 | return new AcceptTrackChange(this.config); 9 | }); 10 | } 11 | } 12 | 13 | export default AcceptTrackChangeService; 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/OENContainersService/OENContainersToolGroupService/OENContainersToolGroup.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class OENContainersToolGroup extends ToolGroup { 6 | tools = []; 7 | title = 'OEN Containers'; 8 | 9 | constructor(@inject('OENContainersTool') OENContainersTool) { 10 | super(); 11 | this.tools = [OENContainersTool]; 12 | } 13 | } 14 | 15 | export default OENContainersToolGroup; 16 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/EnableTrackChangeService/EnableTrackChangeService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import EnableTrackChange from './EnableTrackChange'; 3 | 4 | class EnableTrackChangeService extends Service { 5 | name = 'EnableTrackChangeService'; 6 | 7 | register() { 8 | this.container.bind('EnableTrackChange').toDynamicValue(() => { 9 | return new EnableTrackChange(this.config); 10 | }); 11 | } 12 | } 13 | 14 | export default EnableTrackChangeService; 15 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/RejectTrackChangeService/RejectTrackChangeService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import RejectTrackChange from './RejectTrackChange'; 3 | 4 | class RejectTrackChangeService extends Service { 5 | name = 'RejectTrackChangeService'; 6 | 7 | register() { 8 | this.container.bind('RejectTrackChange').toDynamicValue(() => { 9 | return new RejectTrackChange(this.config); 10 | }); 11 | } 12 | } 13 | 14 | export default RejectTrackChangeService; 15 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BottomInfoService/InfoToolGroupService/InfoTool.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class InfoToolGroup extends ToolGroup { 6 | tools = []; 7 | constructor( 8 | @inject('CounterInfoTool') counterinfotool, 9 | @inject('ShortCutsInfoTool') shortcutsinfotool, 10 | ) { 11 | super(); 12 | this.tools = [shortcutsinfotool, counterinfotool]; 13 | } 14 | } 15 | 16 | export default InfoToolGroup; 17 | -------------------------------------------------------------------------------- /editors/demo/src/HHMI/layout/EditorElements.js: -------------------------------------------------------------------------------- 1 | import { css } from 'styled-components'; 2 | import { th } from '@pubsweet/ui-toolkit'; 3 | 4 | /* All styles regarding ProseMirror surface and elements */ 5 | 6 | const fontWriting = css` 7 | color: ${th('colorText')}; 8 | font-family: ${th('fontWriting')}; 9 | font-size: ${th('fontSizeBase')}; 10 | `; 11 | 12 | export default css` 13 | .ProseMirror { 14 | ${fontWriting} 15 | 16 | .ProseMirror-separator { 17 | display: none !important; 18 | } 19 | } 20 | `; 21 | -------------------------------------------------------------------------------- /wax-questions-service/src/FillTheGapQuestionService/CreateGapService/CreateGapService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import CreateGap from './CreateGap'; 3 | import FillTheGapToolGroupService from '../FillTheGapToolGroupService/FillTheGapToolGroupService'; 4 | 5 | class FillTheGapQuestionService extends Service { 6 | register() { 7 | this.container.bind('CreateGap').to(CreateGap); 8 | } 9 | 10 | dependencies = [new FillTheGapToolGroupService()]; 11 | } 12 | 13 | export default FillTheGapQuestionService; 14 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/AiService/ToggleAiTool.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { v4 as uuidv4 } from 'uuid'; 3 | import { Tools } from 'wax-prosemirror-core'; 4 | import ToggleAiComponent from './components/ToggleAiComponent'; 5 | 6 | class ToggleAiTool extends Tools { 7 | title = 'Toggle Ai'; 8 | icon = 'ai'; 9 | name = 'ToggleAi'; 10 | 11 | renderTool(view) { 12 | return ( 13 | 14 | ); 15 | } 16 | } 17 | 18 | export default ToggleAiTool; 19 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/CustomTagToolGroupService/CustomTagBlockToolGroupService/CustomTagBlockToolGroup.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class CustomTagBlockToolGroup extends ToolGroup { 6 | tools = []; 7 | title = 'Custom Block'; 8 | 9 | constructor(@inject('CustomTagBlockTool') customTagBlock) { 10 | super(); 11 | this.tools = [customTagBlock]; 12 | } 13 | } 14 | 15 | export default CustomTagBlockToolGroup; 16 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/PmPlugins.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-underscore-dangle */ 2 | import { injectable } from 'inversify'; 3 | 4 | @injectable() 5 | export default class PmPlugins { 6 | _plugins = new Map(); 7 | add(key, plugin) { 8 | this._plugins.set(key, plugin); 9 | } 10 | 11 | getAll() { 12 | return [...this._plugins.values()]; 13 | } 14 | 15 | replace(key, plugin) { 16 | this._plugins.delete(key); 17 | this.add(key, plugin); 18 | } 19 | 20 | get(key) { 21 | return this._plugins.get(key); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/NoteService/schema/footNoteNode.js: -------------------------------------------------------------------------------- 1 | const footNoteNode = { 2 | group: 'notes inline', 3 | content: 'inline*', 4 | inline: true, 5 | atom: true, 6 | attrs: { 7 | id: { default: '' }, 8 | }, 9 | toDOM: node => { 10 | return ['footnote', node.attrs]; 11 | }, 12 | parseDOM: [ 13 | { 14 | tag: 'footnote', 15 | getAttrs(dom) { 16 | return { 17 | id: dom.getAttribute('id'), 18 | }; 19 | }, 20 | }, 21 | ], 22 | }; 23 | 24 | export default footNoteNode; 25 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/TrackingAndEditingToolGroupService/TrackingAndEditing.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class TrackingAndEditing extends ToolGroup { 6 | tools = []; 7 | constructor( 8 | @inject('EditingSuggesting') editingSuggesting, 9 | // @inject('FindAndReplace') findAndReplace, 10 | ) { 11 | super(); 12 | this.tools = [editingSuggesting]; 13 | } 14 | } 15 | 16 | export default TrackingAndEditing; 17 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/FullScreenService/FullScreenService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import FullScreenTool from './FullScreenTool'; 3 | import FullScreenToolGroupService from './FullScreenToolGroupService/FullScreenToolGroupService'; 4 | 5 | class FullScreenService extends Service { 6 | name = 'FullScreenService'; 7 | 8 | register() { 9 | this.container.bind('FullScreenTool').to(FullScreenTool); 10 | } 11 | 12 | dependencies = [new FullScreenToolGroupService()]; 13 | } 14 | 15 | export default FullScreenService; 16 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/TitleService/schema/titleNode.js: -------------------------------------------------------------------------------- 1 | const titleNode = { 2 | attrs: { 3 | level: { default: 1 }, 4 | }, 5 | content: 'inline*', 6 | group: 'block', 7 | defining: true, 8 | parseDOM: [ 9 | { 10 | tag: 'h1', 11 | attrs: { level: 1 }, 12 | }, 13 | ], 14 | toDOM(hook, next) { 15 | const attrs = {}; 16 | // eslint-disable-next-line no-param-reassign 17 | hook.value = [`h${hook.node.attrs.level}`, attrs, 0]; 18 | next(); 19 | }, 20 | }; 21 | 22 | export default titleNode; 23 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/CustomTagToolGroupService/CustomTagBlockNewToolGroupService/CustomTagBlockNewToolGroup.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class CustomTagBlockToolGroup extends ToolGroup { 6 | tools = []; 7 | title = 'Custom Block'; 8 | 9 | constructor(@inject('CustomTagBlockNewTool') customTagBlockNewTool) { 10 | super(); 11 | this.tools = [customTagBlockNewTool]; 12 | } 13 | } 14 | 15 | export default CustomTagBlockToolGroup; 16 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/SubTitleService/SubTitleService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import subTitleNode from './schema/subTitleNode'; 3 | import SubTitle from './SubTitle'; 4 | 5 | class SubTitleService extends Service { 6 | register() { 7 | this.container.bind('SubTitle').to(SubTitle); 8 | const createNode = this.container.get('CreateNode'); 9 | createNode( 10 | { 11 | subtitle: subTitleNode, 12 | }, 13 | { toWaxSchema: true }, 14 | ); 15 | } 16 | } 17 | 18 | export default SubTitleService; 19 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/AuthorService/AuthorService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import authorNode from './schema/authorNode'; 3 | import Author from './Author'; 4 | 5 | class AuthorService extends Service { 6 | // boot() {} 7 | 8 | register() { 9 | this.container.bind('Author').to(Author); 10 | const createNode = this.container.get('CreateNode'); 11 | createNode( 12 | { 13 | author: authorNode, 14 | }, 15 | { toWaxSchema: true }, 16 | ); 17 | } 18 | } 19 | 20 | export default AuthorService; 21 | -------------------------------------------------------------------------------- /editors/demo/src/NCBI/layout/EditorElements.js: -------------------------------------------------------------------------------- 1 | import { css } from 'styled-components'; 2 | 3 | import { th } from '@pubsweet/ui-toolkit'; 4 | 5 | /* All styles regarding ProseMirror surface and elements */ 6 | 7 | const fontWriting = css` 8 | color: ${th('colorText')}; 9 | font-family: ${th('fontWriting')}; 10 | font-size: ${th('fontSizeBase')}; 11 | `; 12 | 13 | export default css` 14 | .ProseMirror { 15 | background: white; 16 | line-height: 12px; 17 | width: 492px; 18 | white-space: pre !important; 19 | overflow-x: auto; 20 | ${fontWriting} 21 | } 22 | `; 23 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/SmallCapsService/SmallCapsService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import smallcapsMark from './schema/smallcapsMark'; 3 | import SmallCaps from './SmallCaps'; 4 | 5 | class SmallCapsService extends Service { 6 | register() { 7 | this.container.bind('SmallCaps').to(SmallCaps); 8 | const createMark = this.container.get('CreateMark'); 9 | createMark( 10 | { 11 | smallcaps: smallcapsMark, 12 | }, 13 | { toWaxSchema: true }, 14 | ); 15 | } 16 | } 17 | 18 | export default SmallCapsService; 19 | -------------------------------------------------------------------------------- /editors/demo/src/OEN/config/defaultSchema.js: -------------------------------------------------------------------------------- 1 | const defaultSchema = { 2 | nodes: { 3 | doc: { 4 | content: 'inline*', 5 | }, 6 | text: { 7 | group: 'inline', 8 | }, 9 | paragraph: null, 10 | hard_break: null, 11 | title: { 12 | group: 'inline', 13 | content: 'inline*', 14 | inline: true, 15 | parseDOM: [ 16 | { 17 | tag: 'title', 18 | }, 19 | ], 20 | toDOM(node) { 21 | return ['title', node.attrs, 0]; 22 | }, 23 | }, 24 | }, 25 | marks: {}, 26 | }; 27 | 28 | export default defaultSchema; 29 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/SmallCapsService/schema/smallcapsMark.js: -------------------------------------------------------------------------------- 1 | const smallcapsMark = { 2 | attrs: { 3 | class: { default: 'small-caps' }, 4 | }, 5 | // inclusive: false, 6 | parseDOM: [ 7 | { 8 | tag: 'span.small-caps', 9 | getAttrs(hook, next) { 10 | Object.assign(hook, { 11 | class: hook.dom.getAttribute('class'), 12 | }); 13 | next(); 14 | }, 15 | }, 16 | ], 17 | toDOM(hook, next) { 18 | hook.value = ['span', hook.node.attrs, 0]; 19 | next(); 20 | }, 21 | }; 22 | 23 | export default smallcapsMark; 24 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/ListToolGroupService/Lists.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class Lists extends ToolGroup { 6 | tools = []; 7 | constructor( 8 | @inject('BlockQuote') blockQuote, 9 | @inject('OrderedList') orderedlist, 10 | @inject('BulletList') bulletlist, 11 | @inject('JoinUp') joinup, 12 | @inject('Lift') lift, 13 | ) { 14 | super(); 15 | this.tools = [blockQuote, orderedlist, bulletlist, joinup, lift]; 16 | } 17 | } 18 | 19 | export default Lists; 20 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/SourceNoteService/SourceNoteService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import sourceNoteNode from './schema/sourceNoteNode'; 3 | import SourceNote from './SourceNote'; 4 | 5 | class SourceNoteService extends Service { 6 | register() { 7 | this.container.bind('SourceNote').to(SourceNote); 8 | const createNode = this.container.get('CreateNode'); 9 | createNode( 10 | { 11 | sourceNote: sourceNoteNode, 12 | }, 13 | { toWaxSchema: true }, 14 | ); 15 | } 16 | } 17 | 18 | export default SourceNoteService; 19 | -------------------------------------------------------------------------------- /editors/demo/src/Editoria/config/defaultSchema.js: -------------------------------------------------------------------------------- 1 | const defaultSchema = { 2 | nodes: { 3 | doc: { 4 | content: 'inline*', 5 | }, 6 | text: { 7 | group: 'inline', 8 | }, 9 | paragraph: null, 10 | hard_break: null, 11 | title: { 12 | group: 'inline', 13 | content: 'inline*', 14 | inline: true, 15 | parseDOM: [ 16 | { 17 | tag: 'title', 18 | }, 19 | ], 20 | toDOM(node) { 21 | return ['title', node.attrs, 0]; 22 | }, 23 | }, 24 | }, 25 | marks: {}, 26 | }; 27 | 28 | export default defaultSchema; 29 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/components/ToolGroups.js: -------------------------------------------------------------------------------- 1 | /* eslint no-underscore-dangle: 0 */ 2 | import React from 'react'; 3 | import { v4 as uuidv4 } from 'uuid'; 4 | import ToolGroupComponent from './ToolGroupComponent'; 5 | 6 | const ToolGroups = ({ toolGroups, view }) => { 7 | return toolGroups.map(toolGroup => { 8 | if (toolGroup._toolGroups.length > 0) { 9 | return ; 10 | } 11 | return ( 12 | 13 | ); 14 | }); 15 | }; 16 | 17 | export default ToolGroups; 18 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/ExtractProseService/ExtractProseService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import extractProseNode from './schema/extractProseNode'; 3 | import ExtractProse from './ExtractProse'; 4 | 5 | class ExtractProseService extends Service { 6 | register() { 7 | this.container.bind('ExtractProse').to(ExtractProse); 8 | const createNode = this.container.get('CreateNode'); 9 | createNode( 10 | { 11 | extractProse: extractProseNode, 12 | }, 13 | { toWaxSchema: true }, 14 | ); 15 | } 16 | } 17 | 18 | export default ExtractProseService; 19 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/TrackOptionsToolGroupService/TrackOptions.js: -------------------------------------------------------------------------------- 1 | import { injectable, inject } from 'inversify'; 2 | import { ToolGroup } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class TrackOptions extends ToolGroup { 6 | tools = []; 7 | constructor( 8 | @inject('ShowHideTrackChange') showHideTrackChange, 9 | @inject('AcceptTrackChange') acceptTrackChange, 10 | @inject('RejectTrackChange') rejectTrackChange, 11 | ) { 12 | super(); 13 | this.tools = [showHideTrackChange, acceptTrackChange, rejectTrackChange]; 14 | } 15 | } 16 | 17 | export default TrackOptions; 18 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultServices/ShortCutsService/ShortCutsService.js: -------------------------------------------------------------------------------- 1 | import Service from '../../../Service'; 2 | import ShortCuts from './ShortCuts'; 3 | 4 | export default class ShortCutsService extends Service { 5 | name = 'ShortCutsService'; 6 | 7 | register() { 8 | this.container.bind('ShortCuts').to(ShortCuts).inSingletonScope(); 9 | 10 | this.container.bind('CreateShortCut').toFactory(context => { 11 | return shortCut => { 12 | const shortCutsInstance = context.container.get('ShortCuts'); 13 | shortCutsInstance.addShortCut(shortCut); 14 | }; 15 | }); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /wax-questions-service/src/EssayService/schema/essayContainerNode.js: -------------------------------------------------------------------------------- 1 | const essayContainerNode = { 2 | attrs: { 3 | id: { default: '' }, 4 | class: { default: 'essay' }, 5 | }, 6 | group: 'block questions', 7 | isolating: true, 8 | content: 'block+', 9 | parseDOM: [ 10 | { 11 | tag: 'div.essay', 12 | getAttrs(dom) { 13 | return { 14 | id: dom.getAttribute('id'), 15 | class: dom.getAttribute('class'), 16 | }; 17 | }, 18 | }, 19 | ], 20 | toDOM(node) { 21 | return ['div', node.attrs, 0]; 22 | }, 23 | }; 24 | 25 | export default essayContainerNode; 26 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ExternalAPIContentService/externalApiContent.css: -------------------------------------------------------------------------------- 1 | placeholder-external-api { 2 | display: inline-block; 3 | width: 20px; 4 | } 5 | 6 | placeholder-external-api:before { 7 | position: relative; 8 | top: 3px; 9 | content: url("data:image/svg+xml; utf8, "); 10 | } -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/StrongService/schema/strongMark.js: -------------------------------------------------------------------------------- 1 | const strongMark = { 2 | parseDOM: [ 3 | { tag: 'strong' }, 4 | // This works around a Google Docs misbehavior where 5 | // pasted content will be inexplicably wrapped in `` 6 | // tags with a font-weight normal. 7 | { tag: 'b', getAttrs: node => node.style.fontWeight !== 'normal' && null }, 8 | { 9 | style: 'font-weight', 10 | getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null, 11 | }, 12 | ], 13 | toDOM() { 14 | return ['strong', 0]; 15 | }, 16 | }; 17 | 18 | export default strongMark; 19 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultServices/OverlayService/OverlayService.js: -------------------------------------------------------------------------------- 1 | import Service from '../../../Service'; 2 | import OverlayComponent from './OverlayComponent'; 3 | 4 | export default class OverlayService extends Service { 5 | register() { 6 | this.container.bind('CreateOverlay').toFactory(context => { 7 | return (Component, componentProps, options) => { 8 | const layout = context.container.get('Layout'); 9 | layout.addComponent( 10 | 'waxOverlays', 11 | OverlayComponent(Component, options), 12 | componentProps, 13 | ); 14 | }; 15 | }); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/utilities/track-changes/helpers/removeNode.js: -------------------------------------------------------------------------------- 1 | import { replaceStep } from 'prosemirror-transform'; 2 | import { Selection } from 'prosemirror-state'; 3 | 4 | const removeNode = (tr, node, nodePos, map) => { 5 | const newNodePos = map.map(nodePos); 6 | const selectionBefore = Selection.findFrom(tr.doc.resolve(newNodePos), -1); 7 | const start = selectionBefore.$anchor.pos; 8 | const end = newNodePos + 1; 9 | 10 | const delStep = replaceStep(tr.doc, start, end); 11 | 12 | tr.step(delStep); 13 | const stepMap = delStep.getMap(); 14 | map.appendMap(stepMap); 15 | }; 16 | 17 | export default removeNode; 18 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CodeBlockService/schema/codeBlockNode.js: -------------------------------------------------------------------------------- 1 | const codeBlockNode = { 2 | content: 'text*', 3 | group: 'block', 4 | code: true, 5 | defining: true, 6 | marks: 'comment insertion deletion', 7 | attrs: { params: { default: '' } }, 8 | parseDOM: [ 9 | { 10 | tag: 'pre', 11 | preserveWhitespace: 'full', 12 | getAttrs(dom) { 13 | return { 14 | params: dom.dataset.params, 15 | }; 16 | }, 17 | }, 18 | ], 19 | toDOM(node) { 20 | return ['pre', { 'data-params': node.attrs.params }, ['code', 0]]; 21 | }, 22 | }; 23 | 24 | export default codeBlockNode; 25 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/EpigraphProseService/EpigraphProseService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import epigraphProseNode from './schema/epigraphProseNode'; 3 | import EpigraphProse from './EpigraphProse'; 4 | 5 | class EpigraphProseService extends Service { 6 | register() { 7 | this.container.bind('EpigraphProse').to(EpigraphProse); 8 | const createNode = this.container.get('CreateNode'); 9 | createNode( 10 | { 11 | epigraphProse: epigraphProseNode, 12 | }, 13 | { toWaxSchema: true }, 14 | ); 15 | } 16 | } 17 | 18 | export default EpigraphProseService; 19 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/StrikeThroughService/StrikeThroughService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import strikethroughMark from './schema/strikethroughMark'; 3 | import StrikeThrough from './StrikeThrough'; 4 | 5 | class StrikeThroughService extends Service { 6 | register() { 7 | this.container.bind('StrikeThrough').to(StrikeThrough); 8 | const createMark = this.container.get('CreateMark'); 9 | createMark( 10 | { 11 | strikethrough: strikethroughMark, 12 | }, 13 | { toWaxSchema: true }, 14 | ); 15 | } 16 | } 17 | 18 | export default StrikeThroughService; 19 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/SpecialCharactersService/SpecialCharactersService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import SpecialCharactersTool from './SpecialCharactersTool'; 3 | import SpecialCharactersToolGroupService from './SpecialCharactersToolGroupService/SpecialCharactersToolGroupService'; 4 | 5 | class SpecialCharactersService extends Service { 6 | name = 'SpecialCharactersService'; 7 | 8 | register() { 9 | this.container.bind('SpecialCharactersTool').to(SpecialCharactersTool); 10 | } 11 | 12 | dependencies = [new SpecialCharactersToolGroupService()]; 13 | } 14 | export default SpecialCharactersService; 15 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/ExtractPoetryService/ExtractPoetryService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import extractPoetryNode from './schema/extractPoetryNode'; 3 | import ExtractPoetry from './ExtractPoetry'; 4 | 5 | class ExtractPoetryService extends Service { 6 | register() { 7 | this.container.bind('ExtractPoetry').to(ExtractPoetry); 8 | const createNode = this.container.get('CreateNode'); 9 | createNode( 10 | { 11 | extractPoetry: extractPoetryNode, 12 | }, 13 | { toWaxSchema: true }, 14 | ); 15 | } 16 | } 17 | 18 | export default ExtractPoetryService; 19 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/TitleService/TitleService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import titleNode from './schema/titleNode'; 3 | import Title from './Title'; 4 | 5 | class TitleService extends Service { 6 | register() { 7 | this.container.bind('Title').toDynamicValue(() => { 8 | return new Title(this.config.get('config.OENContainersService')); 9 | }); 10 | const createNode = this.container.get('CreateNode'); 11 | createNode( 12 | { 13 | title: titleNode, 14 | }, 15 | { toWaxSchema: true }, 16 | ); 17 | } 18 | } 19 | 20 | export default TitleService; 21 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/NoteService/note.css: -------------------------------------------------------------------------------- 1 | /* FootNote */ 2 | 3 | .ProseMirror { 4 | counter-reset: footnote!important; 5 | } 6 | 7 | .ProseMirror footnote { 8 | font-variant-numeric: lining-nums proportional-nums; 9 | display: inline-block; 10 | text-align: center; 11 | width: 17px; 12 | height: 17px; 13 | background: white; 14 | border-bottom: 2px solid black; 15 | color: black; 16 | cursor: pointer; 17 | } 18 | 19 | .ProseMirror footnote::after { 20 | content: counter(footnote); 21 | position: relative; 22 | bottom: 2px; 23 | font-size: 16px; 24 | counter-increment: footnote; 25 | } -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/track-changes/helpers/removeNode.js: -------------------------------------------------------------------------------- 1 | import { replaceStep } from 'prosemirror-transform'; 2 | import { Selection } from 'prosemirror-state'; 3 | 4 | const removeNode = (tr, node, nodePos, map) => { 5 | const newNodePos = map.map(nodePos); 6 | const selectionBefore = Selection.findFrom(tr.doc.resolve(newNodePos), -1); 7 | const start = selectionBefore.$anchor.pos; 8 | const end = newNodePos + 1; 9 | 10 | const delStep = replaceStep(tr.doc, start, end); 11 | 12 | tr.step(delStep); 13 | const stepMap = delStep.getMap(); 14 | map.appendMap(stepMap); 15 | }; 16 | 17 | export default removeNode; 18 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/schema/questionNode.js: -------------------------------------------------------------------------------- 1 | const questionNode = { 2 | attrs: { 3 | class: { default: 'multiple-choice-question' }, 4 | id: { default: '' }, 5 | }, 6 | group: 'block questions', 7 | content: 'block*', 8 | // defining: true, 9 | 10 | parseDOM: [ 11 | { 12 | tag: 'div.multiple-choice-question', 13 | getAttrs(dom) { 14 | return { 15 | id: dom.getAttribute('id'), 16 | class: dom.getAttribute('class'), 17 | }; 18 | }, 19 | }, 20 | ], 21 | toDOM: node => ['div', node.attrs, 0], 22 | }; 23 | 24 | export default questionNode; 25 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/ApplicationContext.js: -------------------------------------------------------------------------------- 1 | /* eslint react/prop-types: 0 */ 2 | /* eslint react/destructuring-assignment: 0 */ 3 | import React, { useEffect, useState } from 'react'; 4 | 5 | export const ApplicationContext = React.createContext({ 6 | app: null, 7 | getPlugins: null, 8 | }); 9 | 10 | export default ({ app, children }) => { 11 | const [application, setApplication] = useState(app); 12 | 13 | useEffect(() => { 14 | setApplication({ ...app }); 15 | }, [app]); 16 | 17 | return ( 18 | 19 | {children} 20 | 21 | ); 22 | }; 23 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultServices/OverlayService/OverLay.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/destructuring-assignment */ 2 | /* eslint-disable react/jsx-props-no-spreading */ 3 | import React from 'react'; 4 | import styled from 'styled-components'; 5 | 6 | const OverlayContainer = styled.div` 7 | left: ${props => `${props.position.left}px`}; 8 | position: ${props => props.position.position}; 9 | top: ${props => `${props.position.top}px`}; 10 | z-index: ${props => props.position.zIndex}; 11 | `; 12 | 13 | const Overlay = props => ( 14 | {props.children} 15 | ); 16 | 17 | export default Overlay; 18 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/EpigraphPoetryService/EpigraphPoetryService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import epigraphPoetryNode from './schema/epigraphPoetryNode'; 3 | import EpigraphPoetry from './EpigraphPoetry'; 4 | 5 | class EpigraphPoetryService extends Service { 6 | register() { 7 | this.container.bind('EpigraphPoetry').to(EpigraphPoetry); 8 | const createNode = this.container.get('CreateNode'); 9 | createNode( 10 | { 11 | epigraphPoetry: epigraphPoetryNode, 12 | }, 13 | { toWaxSchema: true }, 14 | ); 15 | } 16 | } 17 | 18 | export default EpigraphPoetryService; 19 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/plugins/MoveCursorPlugin.js: -------------------------------------------------------------------------------- 1 | import { Plugin, PluginKey } from 'prosemirror-state'; 2 | 3 | const testPlugin = new PluginKey('moveCursorPlugin'); 4 | 5 | export default () => { 6 | return new Plugin({ 7 | key: testPlugin, 8 | filterTransaction: (transaction, state, b) => { 9 | state.doc.descendants((editorNode, pos) => { 10 | if (editorNode.type.name === 'fill_the_gap_container') { 11 | if (transaction.selection.from - 2 === pos) { 12 | return false; 13 | } 14 | } 15 | }); 16 | 17 | return true; 18 | }, 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /editors/demo/src/NCBI/layout/EditorMiniElements.js: -------------------------------------------------------------------------------- 1 | import { css } from 'styled-components'; 2 | 3 | import { th } from '@pubsweet/ui-toolkit'; 4 | 5 | /* All styles regarding ProseMirror surface and elements */ 6 | 7 | const fontWriting = css` 8 | color: ${th('colorText')}; 9 | font-family: ${th('fontWriting')}; 10 | font-size: ${th('fontSizeBase')}; 11 | `; 12 | 13 | export default css` 14 | .ProseMirror { 15 | background: white; 16 | counter-reset: footnote; 17 | line-height: 12px; 18 | width: 497px; 19 | ${fontWriting} 20 | } 21 | 22 | .ProseMirror title { 23 | display: inline; 24 | font-size: 14px; 25 | } 26 | `; 27 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/CustomTagBlockService/CustomTagBlockService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import customBlockNode from './schema/customBlockNode'; 3 | import CustomTagBlockTool from './CustomTagBlockTool'; 4 | 5 | class CustomTagBlockService extends Service { 6 | register() { 7 | this.container.bind('CustomTagBlockTool').to(CustomTagBlockTool); 8 | const createNode = this.container.get('CreateNode'); 9 | createNode( 10 | { 11 | customTagBlock: customBlockNode, 12 | }, 13 | { toWaxSchema: true }, 14 | ); 15 | } 16 | } 17 | 18 | export default CustomTagBlockService; 19 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/OENContainersService/schema/OenSectionNode.js: -------------------------------------------------------------------------------- 1 | const OenSectionNode = { 2 | content: 'block+', 3 | group: 'block', 4 | attrs: { 5 | id: { default: '' }, 6 | class: { default: 'section' }, 7 | }, 8 | defining: true, 9 | parseDOM: [ 10 | { 11 | tag: 'section', 12 | getAttrs(dom) { 13 | return { 14 | id: dom.getAttribute('id'), 15 | class: dom.getAttribute('class'), 16 | type: dom.dataset.group, 17 | }; 18 | }, 19 | }, 20 | ], 21 | toDOM(node) { 22 | return ['section', node.attrs, 0]; 23 | }, 24 | }; 25 | 26 | export default OenSectionNode; 27 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ImageService/schema/figureCaptionNode.js: -------------------------------------------------------------------------------- 1 | const figureCaptionNode = { 2 | content: 'inline*', 3 | group: 'figure', 4 | draggable: false, 5 | attrs: { 6 | id: { default: '' }, 7 | class: { default: '' }, 8 | // tabindex: { default: 0 }, 9 | }, 10 | parseDOM: [ 11 | { 12 | tag: 'figcaption', 13 | getAttrs(dom) { 14 | return { 15 | id: dom.getAttribute('id'), 16 | class: dom.getAttribute('class'), 17 | }; 18 | }, 19 | }, 20 | ], 21 | toDOM: node => { 22 | return ['figcaption', node.attrs, 0]; 23 | }, 24 | }; 25 | 26 | export default figureCaptionNode; 27 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/SubscriptService/SubscriptService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import subscriptMark from './schema/subscriptMark'; 3 | import Subscript from './Subscript'; 4 | import './subscript.css'; 5 | 6 | class SubscriptService extends Service { 7 | name = 'SubscriptService'; 8 | 9 | register() { 10 | this.container.bind('Subscript').to(Subscript); 11 | const createMark = this.container.get('CreateMark'); 12 | createMark( 13 | { 14 | subscript: subscriptMark, 15 | }, 16 | { toWaxSchema: true }, 17 | ); 18 | } 19 | } 20 | 21 | export default SubscriptService; 22 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TrackChangeService/ShowHideTrackChangeService/ShowHideTrackChange.js: -------------------------------------------------------------------------------- 1 | import { injectable } from 'inversify'; 2 | import { Tools } from 'wax-prosemirror-core'; 3 | 4 | @injectable() 5 | class ShowHideTrackChange extends Tools { 6 | title = 'Show/Hide Changes'; 7 | icon = 'showTrack'; 8 | label = 'Show suggestions'; 9 | name = 'ShowHideTrackChange'; 10 | 11 | get run() { 12 | return (state, dispatch) => {}; 13 | } 14 | 15 | select = (state, activeViewId, activeView) => { 16 | return true; 17 | }; 18 | 19 | get active() { 20 | return state => {}; 21 | } 22 | } 23 | 24 | export default ShowHideTrackChange; 25 | -------------------------------------------------------------------------------- /wax-questions-service/src/EssayService/schema/essayAnswerNode.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuidv4 } from 'uuid'; 2 | 3 | const essayAnswerNode = { 4 | attrs: { 5 | class: { default: 'essay-answer' }, 6 | id: { default: uuidv4() }, 7 | }, 8 | group: 'block questions', 9 | content: 'block*', 10 | defining: true, 11 | 12 | parseDOM: [ 13 | { 14 | tag: 'div.essay-answer', 15 | getAttrs(dom) { 16 | return { 17 | id: dom.getAttribute('id'), 18 | class: dom.getAttribute('class'), 19 | }; 20 | }, 21 | }, 22 | ], 23 | toDOM: node => ['div', node.attrs, 0], 24 | }; 25 | 26 | export default essayAnswerNode; 27 | -------------------------------------------------------------------------------- /wax-questions-service/src/EssayService/schema/essayPromptNode.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuidv4 } from 'uuid'; 2 | 3 | const essayPromptNode = { 4 | attrs: { 5 | class: { default: 'essay-prompt' }, 6 | id: { default: uuidv4() }, 7 | }, 8 | group: 'block questions', 9 | content: 'block*', 10 | defining: true, 11 | 12 | parseDOM: [ 13 | { 14 | tag: 'div.essay-prompt', 15 | getAttrs(dom) { 16 | return { 17 | id: dom.getAttribute('id'), 18 | class: dom.getAttribute('class'), 19 | }; 20 | }, 21 | }, 22 | ], 23 | toDOM: node => ['div', node.attrs, 0], 24 | }; 25 | 26 | export default essayPromptNode; 27 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BaseService/SaveService/Save.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { isEmpty } from 'lodash'; 3 | import { injectable } from 'inversify'; 4 | import { Tools, icons } from 'wax-prosemirror-core'; 5 | import SaveButton from './components/SaveButton'; 6 | 7 | @injectable() 8 | export default class Save extends Tools { 9 | title = 'Save changes'; 10 | icon = 'save'; 11 | name = 'Save'; 12 | content = icons.save; 13 | name = 'Save'; 14 | 15 | renderTool(view) { 16 | if (isEmpty(view)) return null; 17 | return this.isDisplayed() ? ( 18 | 19 | ) : null; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/ParagraphContinuedService/ParagraphContinuedService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import paragraphContNode from './schema/paragraphContNode'; 3 | import ParagraphContinued from './ParagraphContinued'; 4 | 5 | class ParagraphContinuedService extends Service { 6 | register() { 7 | this.container.bind('ParagraphContinued').to(ParagraphContinued); 8 | const createNode = this.container.get('CreateNode'); 9 | createNode( 10 | { 11 | paragraphCont: paragraphContNode, 12 | }, 13 | { toWaxSchema: true }, 14 | ); 15 | } 16 | } 17 | 18 | export default ParagraphContinuedService; 19 | -------------------------------------------------------------------------------- /wax-questions-service/src/EssayService/schema/essayQuestionNode.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuidv4 } from 'uuid'; 2 | 3 | const essayQuestionNode = { 4 | attrs: { 5 | class: { default: 'essay-question' }, 6 | id: { default: uuidv4() }, 7 | }, 8 | group: 'block questions', 9 | content: 'block*', 10 | // defining: true, 11 | 12 | parseDOM: [ 13 | { 14 | tag: 'div.essay-question', 15 | getAttrs(dom) { 16 | return { 17 | id: dom.getAttribute('id'), 18 | class: dom.getAttribute('class'), 19 | }; 20 | }, 21 | }, 22 | ], 23 | toDOM: node => ['div', node.attrs, 0], 24 | }; 25 | 26 | export default essayQuestionNode; 27 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/CustomTagInlineService/CustomTagInlineTool.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { v4 as uuidv4 } from 'uuid'; 3 | import { Tools } from 'wax-prosemirror-core'; 4 | import CustomTagInlineComponent from '../components/CustomTagInlineComponent'; 5 | 6 | class CustomTagInLineTool extends Tools { 7 | title = 'Custom Tag Inline'; 8 | icon = 'cutomInline'; 9 | name = 'CustomTagInline'; 10 | 11 | renderTool(view) { 12 | return ( 13 | 18 | ); 19 | } 20 | } 21 | 22 | export default CustomTagInLineTool; 23 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/AuthorService/schema/authorNode.js: -------------------------------------------------------------------------------- 1 | const authorNode = { 2 | content: 'inline*', 3 | group: 'block', 4 | priority: 0, 5 | defining: true, 6 | attrs: { 7 | class: { default: 'author' }, 8 | }, 9 | parseDOM: [ 10 | { 11 | tag: 'p.author', 12 | getAttrs(hook, next) { 13 | Object.assign(hook, { 14 | class: hook.dom.getAttribute('class'), 15 | }); 16 | next(); 17 | }, 18 | }, 19 | ], 20 | toDOM(hook, next) { 21 | const attrs = { class: hook.node.attrs.class }; 22 | hook.value = ['p', attrs, 0]; 23 | next(); 24 | }, 25 | }; 26 | 27 | export default authorNode; 28 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/LiftService/Lift.js: -------------------------------------------------------------------------------- 1 | import { lift } from 'prosemirror-commands'; 2 | import { injectable } from 'inversify'; 3 | import { Tools } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | export default class Lift extends Tools { 7 | title = 'Lift out of enclosing block'; 8 | icon = 'indentDecrease'; 9 | name = 'Lift'; 10 | 11 | select = (state, activeViewId, activeView) => { 12 | const { disallowedTools } = activeView.props; 13 | if (disallowedTools.includes('lift')) return false; 14 | return lift(state); 15 | }; 16 | 17 | get run() { 18 | return lift; 19 | } 20 | 21 | get enable() { 22 | return lift; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/schema/multipleChoiceContainerNode.js: -------------------------------------------------------------------------------- 1 | const multipleChoiceContainerNode = { 2 | attrs: { 3 | id: { default: '' }, 4 | class: { default: 'multiple-choice' }, 5 | }, 6 | group: 'block questions', 7 | atom: true, 8 | content: 'block+', 9 | parseDOM: [ 10 | { 11 | tag: 'div.multiple-choice', 12 | getAttrs(dom) { 13 | return { 14 | id: dom.getAttribute('id'), 15 | class: dom.getAttribute('class'), 16 | }; 17 | }, 18 | }, 19 | ], 20 | toDOM(node) { 21 | return ['div', node.attrs, 0]; 22 | }, 23 | }; 24 | 25 | export default multipleChoiceContainerNode; 26 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/SubTitleService/schema/subTitleNode.js: -------------------------------------------------------------------------------- 1 | const subTitleNode = { 2 | content: 'inline*', 3 | group: 'block', 4 | priority: 0, 5 | defining: true, 6 | attrs: { 7 | class: { default: 'cst' }, 8 | }, 9 | parseDOM: [ 10 | { 11 | tag: 'p.cst', 12 | getAttrs(hook, next) { 13 | Object.assign(hook, { 14 | class: hook.dom.getAttribute('class'), 15 | }); 16 | next(); 17 | }, 18 | }, 19 | ], 20 | toDOM(hook, next) { 21 | const attrs = { class: hook.node.attrs.class }; 22 | hook.value = ['p', attrs, 0]; 23 | next(); 24 | }, 25 | }; 26 | 27 | export default subTitleNode; 28 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/SuperscriptService/SuperscriptService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import superscriptMark from './schema/superscriptMark'; 3 | import Superscript from './Superscript'; 4 | import './superscript.css'; 5 | 6 | class SuperscriptService extends Service { 7 | name = 'SuperscriptService'; 8 | 9 | register() { 10 | this.container.bind('Superscript').to(Superscript); 11 | const createMark = this.container.get('CreateMark'); 12 | createMark( 13 | { 14 | superscript: superscriptMark, 15 | }, 16 | { toWaxSchema: true }, 17 | ); 18 | } 19 | } 20 | 21 | export default SuperscriptService; 22 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/StateContext.js: -------------------------------------------------------------------------------- 1 | /* eslint react/prop-types: 0 */ 2 | /* eslint react/destructuring-assignment: 0 */ 3 | import React, { useState } from 'react'; 4 | 5 | export const StateContext = React.createContext({ 6 | state: null, 7 | }); 8 | 9 | export default ({ state, children }) => { 10 | const [context, setContext] = useState(state); 11 | 12 | return ( 13 | { 17 | setContext({ 18 | ...context, 19 | state: st, 20 | }); 21 | }, 22 | }} 23 | > 24 | {children} 25 | 26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/CustomTagBlockNewService/CustomTagBlockNewService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import customBlockNode from '../CustomTagBlockService/schema/customBlockNode'; 3 | import CustomTagBlockNewTool from './CustomTagBlockNewTool'; 4 | 5 | class CustomTagBlockNewService extends Service { 6 | register() { 7 | this.container.bind('CustomTagBlockNewTool').to(CustomTagBlockNewTool); 8 | const createNode = this.container.get('CreateNode'); 9 | createNode( 10 | { 11 | customTagBlock: customBlockNode, 12 | }, 13 | { toWaxSchema: true }, 14 | ); 15 | } 16 | } 17 | 18 | export default CustomTagBlockNewService; 19 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # docker 2 | Dockerfile* 3 | docker-compose* 4 | 5 | # git 6 | .git 7 | .gitignore 8 | 9 | # npm & yarn 10 | node_modules 11 | npm-debug.log 12 | package-lock.json 13 | yarn-error.log 14 | 15 | # misc 16 | .devcontainer 17 | .DS_Store 18 | .vscode 19 | app.pid 20 | 21 | # environment files 22 | .env* 23 | *.env 24 | 25 | # app 26 | editors/demo/build/ 27 | coverage/ 28 | cypress/ 29 | logs/ 30 | stories/ 31 | tmp/ 32 | 33 | # Include README.md and LICENSE.md, exlcude the rest 34 | *.md 35 | !README.md 36 | !LICENSE.md 37 | 38 | # development config files 39 | # .eslintrc.js 40 | .commitlintrc.js 41 | .cz-config.js 42 | .gitlab-ci.yml 43 | .linstagedrc.js 44 | # .prettierrc.js 45 | # .stylelintrc.js 46 | -------------------------------------------------------------------------------- /wax-citation-service/src/CitationCalloutNodeView.js: -------------------------------------------------------------------------------- 1 | import { AbstractNodeView } from 'wax-prosemirror-core'; 2 | 3 | export default class CitationCalloutNodeView extends AbstractNodeView { 4 | constructor( 5 | node, 6 | view, 7 | getPos, 8 | decorations, 9 | createPortal, 10 | Component, 11 | context, 12 | ) { 13 | super(node, view, getPos, decorations, createPortal, Component, context); 14 | 15 | this.node = node; 16 | this.outerView = view; 17 | this.getPos = getPos; 18 | this.context = context; 19 | } 20 | 21 | static name() { 22 | return 'citation_callout'; 23 | } 24 | 25 | stopEvent(event) { 26 | return super.stopEvent(event); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/NoteService/components/NoteNumber.js: -------------------------------------------------------------------------------- 1 | /* eslint react/prop-types: 0 */ 2 | import React from 'react'; 3 | import styled from 'styled-components'; 4 | 5 | const NoteNumberStyled = styled.div` 6 | display: flex; 7 | margin-right: 10px; 8 | margin-top: 10px; 9 | position: absolute; 10 | left: -20px; 11 | 12 | &:after { 13 | content: counter(footnote-view) '.'; 14 | counter-increment: footnote-view; 15 | cursor: pointer; 16 | font-size: 14px; 17 | font-weight: 500; 18 | } 19 | `; 20 | 21 | const onClick = () => {}; 22 | 23 | const NoteNumber = ({ number }) => { 24 | return ; 25 | }; 26 | 27 | export default NoteNumber; 28 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/SourceNoteService/schema/sourceNoteNode.js: -------------------------------------------------------------------------------- 1 | const sourceNoteNode = { 2 | content: 'inline*', 3 | group: 'block', 4 | priority: 0, 5 | defining: true, 6 | attrs: { 7 | class: { default: 'source-note' }, 8 | }, 9 | parseDOM: [ 10 | { 11 | tag: 'p.source-note', 12 | getAttrs(hook, next) { 13 | Object.assign(hook, { 14 | class: hook.dom.getAttribute('class'), 15 | }); 16 | next(); 17 | }, 18 | }, 19 | ], 20 | toDOM(hook, next) { 21 | const attrs = { class: hook.node.attrs.class }; 22 | hook.value = ['p', attrs, 0]; 23 | next(); 24 | }, 25 | }; 26 | 27 | export default sourceNoteNode; 28 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/schema/questionTrueFalseSingleNode.js: -------------------------------------------------------------------------------- 1 | const questionTrueFalseNode = { 2 | attrs: { 3 | id: { default: '' }, 4 | class: { default: 'true-false-question-single' }, 5 | }, 6 | group: 'block questions', 7 | content: 'block*', 8 | // defining: true, 9 | parseDOM: [ 10 | { 11 | tag: 'div.true-false-question-single', 12 | getAttrs(dom) { 13 | return { 14 | id: dom.getAttribute('id'), 15 | class: dom.getAttribute('class'), 16 | }; 17 | }, 18 | }, 19 | ], 20 | toDOM: node => ['div', node.attrs, 0], 21 | }; 22 | 23 | export default questionTrueFalseNode; 24 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/HighlightService/schema/highlightMark.js: -------------------------------------------------------------------------------- 1 | const highlightMark = { 2 | attrs: { 3 | style: { default: null }, 4 | class: { default: 'highlight' }, 5 | }, 6 | inclusive: false, 7 | parseDOM: [ 8 | { 9 | tag: 'span.highlight', 10 | getAttrs(hook, next) { 11 | Object.assign(hook, { 12 | class: hook.dom.getAttribute('class'), 13 | style: hook.dom.getAttribute('style'), 14 | }); 15 | next(); 16 | }, 17 | }, 18 | ], 19 | toDOM(hook, next) { 20 | // eslint-disable-next-line no-param-reassign 21 | hook.value = ['span', hook.node.attrs, 0]; 22 | next(); 23 | }, 24 | }; 25 | 26 | export default highlightMark; 27 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/OENContainersService/schema/OenAsideNode.js: -------------------------------------------------------------------------------- 1 | const OenAsideNode = { 2 | content: 'block+', 3 | group: 'block', 4 | attrs: { 5 | id: { default: '' }, 6 | class: { default: '' }, 7 | }, 8 | defining: true, 9 | parseDOM: [ 10 | { 11 | tag: 'aside', 12 | getAttrs(dom) { 13 | return { 14 | id: dom.getAttribute('id'), 15 | class: dom.getAttribute('class'), 16 | }; 17 | }, 18 | }, 19 | ], 20 | toDOM(node) { 21 | return [ 22 | 'aside', 23 | { 24 | id: node.attrs.id, 25 | class: node.attrs.class, 26 | }, 27 | 0, 28 | ]; 29 | }, 30 | }; 31 | 32 | export default OenAsideNode; 33 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/ExtractProseService/schema/extractProseNode.js: -------------------------------------------------------------------------------- 1 | const extractProseNode = { 2 | content: 'inline*', 3 | group: 'block', 4 | priority: 0, 5 | defining: true, 6 | attrs: { 7 | class: { default: 'extract-prose' }, 8 | }, 9 | parseDOM: [ 10 | { 11 | tag: 'p.extract-prose', 12 | getAttrs(hook, next) { 13 | Object.assign(hook, { 14 | class: hook.dom.getAttribute('class'), 15 | }); 16 | next(); 17 | }, 18 | }, 19 | ], 20 | toDOM(hook, next) { 21 | const attrs = { class: hook.node.attrs.class }; 22 | hook.value = ['p', attrs, 0]; 23 | next(); 24 | }, 25 | }; 26 | 27 | export default extractProseNode; 28 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/ExtractPoetryService/schema/extractPoetryNode.js: -------------------------------------------------------------------------------- 1 | const extractPoetryNode = { 2 | content: 'inline*', 3 | group: 'block', 4 | priority: 0, 5 | defining: true, 6 | attrs: { 7 | class: { default: 'extract-poetry' }, 8 | }, 9 | parseDOM: [ 10 | { 11 | tag: 'p.extract-poetry', 12 | getAttrs(hook, next) { 13 | Object.assign(hook, { 14 | class: hook.dom.getAttribute('class'), 15 | }); 16 | next(); 17 | }, 18 | }, 19 | ], 20 | toDOM(hook, next) { 21 | const attrs = { class: hook.node.attrs.class }; 22 | hook.value = ['p', attrs, 0]; 23 | next(); 24 | }, 25 | }; 26 | 27 | export default extractPoetryNode; 28 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/EpigraphProseService/schema/epigraphProseNode.js: -------------------------------------------------------------------------------- 1 | const epigraphProseNode = { 2 | content: 'inline*', 3 | group: 'block', 4 | priority: 0, 5 | defining: true, 6 | attrs: { 7 | class: { default: 'epigraph-prose' }, 8 | }, 9 | parseDOM: [ 10 | { 11 | tag: 'p.epigraph-prose', 12 | getAttrs(hook, next) { 13 | Object.assign(hook, { 14 | class: hook.dom.getAttribute('class'), 15 | }); 16 | next(); 17 | }, 18 | }, 19 | ], 20 | toDOM(hook, next) { 21 | const attrs = { class: hook.node.attrs.class }; 22 | hook.value = ['p', attrs, 0]; 23 | next(); 24 | }, 25 | }; 26 | 27 | export default epigraphProseNode; 28 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/ParagraphContinuedService/schema/paragraphContNode.js: -------------------------------------------------------------------------------- 1 | const paragraphContNode = { 2 | content: 'inline*', 3 | group: 'block', 4 | priority: 0, 5 | defining: true, 6 | attrs: { 7 | class: { default: 'paragraph-cont' }, 8 | }, 9 | parseDOM: [ 10 | { 11 | tag: 'p.paragraph-cont', 12 | getAttrs(hook, next) { 13 | Object.assign(hook, { 14 | class: hook.dom.getAttribute('class'), 15 | }); 16 | next(); 17 | }, 18 | }, 19 | ], 20 | toDOM(hook, next) { 21 | const attrs = { class: hook.node.attrs.class }; 22 | hook.value = ['p', attrs, 0]; 23 | next(); 24 | }, 25 | }; 26 | 27 | export default paragraphContNode; 28 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/EpigraphPoetryService/schema/epigraphPoetryNode.js: -------------------------------------------------------------------------------- 1 | const epigraphPoetryNode = { 2 | content: 'inline*', 3 | group: 'block', 4 | priority: 0, 5 | defining: true, 6 | attrs: { 7 | class: { default: 'epigraph-poetry' }, 8 | }, 9 | parseDOM: [ 10 | { 11 | tag: 'p.epigraph-poetry', 12 | getAttrs(hook, next) { 13 | Object.assign(hook, { 14 | class: hook.dom.getAttribute('class'), 15 | }); 16 | next(); 17 | }, 18 | }, 19 | ], 20 | toDOM(hook, next) { 21 | const attrs = { class: hook.node.attrs.class }; 22 | hook.value = ['p', attrs, 0]; 23 | next(); 24 | }, 25 | }; 26 | 27 | export default epigraphPoetryNode; 28 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseQuestionService/schema/trueFalseContainerNode.js: -------------------------------------------------------------------------------- 1 | const trueFalseContainerNode = { 2 | attrs: { 3 | id: { default: '' }, 4 | class: { default: 'true-false' }, 5 | }, 6 | group: 'block questions', 7 | atom: true, 8 | selectable: true, 9 | draggable: true, 10 | content: 'block*', 11 | parseDOM: [ 12 | { 13 | tag: 'div.true-false', 14 | getAttrs(dom) { 15 | return { 16 | id: dom.getAttribute('id'), 17 | class: dom.getAttribute('class'), 18 | }; 19 | }, 20 | }, 21 | ], 22 | toDOM(node) { 23 | return ['div', node.attrs, 0]; 24 | }, 25 | }; 26 | 27 | export default trueFalseContainerNode; 28 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/schema/questionSingleNode.js: -------------------------------------------------------------------------------- 1 | const questionSingleNode = { 2 | attrs: { 3 | id: { default: '' }, 4 | class: { default: 'multiple-choice-question-single' }, 5 | }, 6 | group: 'block questions', 7 | content: 'block*', 8 | // defining: true, 9 | 10 | // atom: true, 11 | parseDOM: [ 12 | { 13 | tag: 'div.multiple-choice-question-single', 14 | getAttrs(dom) { 15 | return { 16 | id: dom.getAttribute('id'), 17 | class: dom.getAttribute('class'), 18 | }; 19 | }, 20 | }, 21 | ], 22 | toDOM: node => ['div', node.attrs, 0], 23 | }; 24 | 25 | export default questionSingleNode; 26 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/LiftService/LiftService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import { liftListItem, sinkListItem } from 'prosemirror-schema-list'; 3 | import Lift from './Lift'; 4 | 5 | class LiftService extends Service { 6 | register() { 7 | this.container.bind('Lift').to(Lift); 8 | const CreateShortCut = this.container.get('CreateShortCut'); 9 | CreateShortCut({ 10 | 'Mod-[': (state, dispatch) => 11 | liftListItem(state.schema.nodes.list_item)(state, dispatch), 12 | }); 13 | CreateShortCut({ 14 | 'Mod-]': (state, dispatch) => 15 | sinkListItem(state.schema.nodes.list_item)(state, dispatch), 16 | }); 17 | } 18 | } 19 | 20 | export default LiftService; 21 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/HighlightService/HightlightService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import highlightMark from './schema/highlightMark'; 3 | import TextHighlightTool from './TextHighlightTool'; 4 | import TextHighlightToolGroupServices from './TextHighlightToolGroupService/TextHighlightToolGroupService'; 5 | 6 | export default class HighlightService extends Service { 7 | register() { 8 | this.container.bind('TextHighlightTool').to(TextHighlightTool); 9 | const createMark = this.container.get('CreateMark'); 10 | createMark( 11 | { 12 | highlight: highlightMark, 13 | }, 14 | { toWaxSchema: true }, 15 | ); 16 | } 17 | 18 | dependencies = [new TextHighlightToolGroupServices()]; 19 | } 20 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/StrongService/StrongService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import { toggleMark } from 'prosemirror-commands'; 3 | import strongMark from './schema/strongMark'; 4 | import Strong from './Strong'; 5 | import './strong.css'; 6 | 7 | class StrongService extends Service { 8 | register() { 9 | this.container.bind('Strong').to(Strong); 10 | const createMark = this.container.get('CreateMark'); 11 | const CreateShortCut = this.container.get('CreateShortCut'); 12 | 13 | createMark({ 14 | strong: strongMark, 15 | }); 16 | 17 | CreateShortCut({ 18 | 'Mod-b': toggleMark(this.schema.marks.strong), 19 | }); 20 | } 21 | } 22 | 23 | export default StrongService; 24 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/CodeService/CodeService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import { toggleMark } from 'prosemirror-commands'; 3 | import codeMark from './schema/codeMark'; 4 | import Code from './Code'; 5 | 6 | class CodeService extends Service { 7 | register() { 8 | this.container.bind('Code').to(Code); 9 | const CreateShortCut = this.container.get('CreateShortCut'); 10 | 11 | const createMark = this.container.get('CreateMark'); 12 | createMark( 13 | { 14 | code: codeMark, 15 | }, 16 | { toWaxSchema: true }, 17 | ); 18 | 19 | CreateShortCut({ 20 | 'Mod-`': toggleMark(this.schema.marks.code), 21 | }); 22 | } 23 | } 24 | 25 | export default CodeService; 26 | -------------------------------------------------------------------------------- /wax-questions-service/src/FillTheGapQuestionService/schema/fillTheGapContainerNode.js: -------------------------------------------------------------------------------- 1 | const fillTheGapContainerNode = { 2 | attrs: { 3 | id: { default: '' }, 4 | class: { default: 'fill-the-gap' }, 5 | feedback: { default: '' }, 6 | }, 7 | group: 'block questions', 8 | isolating: true, 9 | content: 'paragraph+', 10 | parseDOM: [ 11 | { 12 | tag: 'div.fill-the-gap', 13 | getAttrs(dom) { 14 | return { 15 | id: dom.getAttribute('id'), 16 | class: dom.getAttribute('class'), 17 | feedback: dom.getAttribute('feedback'), 18 | }; 19 | }, 20 | }, 21 | ], 22 | toDOM(node) { 23 | return ['div', node.attrs, 0]; 24 | }, 25 | }; 26 | 27 | export default fillTheGapContainerNode; 28 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/index.js: -------------------------------------------------------------------------------- 1 | import ExtractPoetryService from './ExtractPoetryService/ExtractPoetryService'; 2 | import ExtractProseService from './ExtractProseService/ExtractProseService'; 3 | import ParagraphContinuedService from './ParagraphContinuedService/ParagraphContinuedService'; 4 | import ParagraphService from './ParagraphService/ParagraphService'; 5 | import SourceNoteService from './SourceNoteService/SourceNoteService'; 6 | import TextToolGroupService from './TextToolGroupService/TextToolGroupService'; 7 | 8 | export default [ 9 | new ExtractPoetryService(), 10 | new ExtractProseService(), 11 | new ParagraphContinuedService(), 12 | new ParagraphService(), 13 | new SourceNoteService(), 14 | new TextToolGroupService(), 15 | ]; 16 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseQuestionService/schema/questionTrueFalseNode.js: -------------------------------------------------------------------------------- 1 | const questionTrueFalseNode = { 2 | attrs: { 3 | id: { default: '' }, 4 | class: { default: 'true-false-question' }, 5 | }, 6 | group: 'block questions', 7 | // content: 'paragraph* bulletlist* orderedlist*', 8 | content: 'block*', 9 | // defining: true, 10 | 11 | // atom: true, 12 | parseDOM: [ 13 | { 14 | tag: 'div.true-false-question', 15 | getAttrs(dom) { 16 | return { 17 | id: dom.getAttribute('id'), 18 | class: dom.getAttribute('class'), 19 | }; 20 | }, 21 | }, 22 | ], 23 | toDOM: node => ['div', node.attrs, 0], 24 | }; 25 | 26 | export default questionTrueFalseNode; 27 | -------------------------------------------------------------------------------- /wax-questions-service/src/FillTheGapQuestionService/schema/fillTheGapNode.js: -------------------------------------------------------------------------------- 1 | const fillTheGapNode = { 2 | attrs: { 3 | id: { default: '' }, 4 | class: { default: 'fill-the-gap' }, 5 | answer: { default: '' }, 6 | }, 7 | group: 'inline', 8 | content: 'text*', 9 | inline: true, 10 | atom: true, 11 | excludes: 'fill_the_gap', 12 | parseDOM: [ 13 | { 14 | tag: 'span.fill-the-gap', 15 | getAttrs(dom) { 16 | return { 17 | id: dom.getAttribute('id'), 18 | class: dom.getAttribute('class'), 19 | answer: dom.getAttribute('answer'), 20 | }; 21 | }, 22 | }, 23 | ], 24 | toDOM: node => { 25 | return ['span', node.attrs, 0]; 26 | }, 27 | }; 28 | 29 | export default fillTheGapNode; 30 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultServices/RulesService/RulesService.js: -------------------------------------------------------------------------------- 1 | import Service from '../../../Service'; 2 | import Rules from './Rules'; 3 | 4 | export default class RulesService extends Service { 5 | name = 'RulesService'; 6 | 7 | boot() { 8 | const configRules = this.app.config.get('config.RulesService'); 9 | const createRule = this.container.get('CreateRule'); 10 | if (configRules) createRule(configRules); 11 | } 12 | 13 | register() { 14 | this.container.bind('Rules').to(Rules).inSingletonScope(); 15 | this.container.bind('CreateRule').toFactory(context => { 16 | return rule => { 17 | const ruleInstance = context.container.get('Rules'); 18 | ruleInstance.addRule(rule); 19 | }; 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/BlockQuoteService/BlockQuoteService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import blockQuoteNode from './schema/blockQuoteNode'; 3 | import BlockQuote from './BlockQuote'; 4 | import BlockQuoteToolGroupService from './BlockQuoteToolGroupService/BlockQuoteToolGroupService'; 5 | import './blockQuote.css'; 6 | 7 | class BlockQuoteService extends Service { 8 | name = 'BlockQuoteService'; 9 | 10 | register() { 11 | this.container.bind('BlockQuote').to(BlockQuote); 12 | const createNode = this.container.get('CreateNode'); 13 | createNode({ 14 | blockquote: blockQuoteNode, 15 | }); 16 | } 17 | 18 | dependencies = [new BlockQuoteToolGroupService()]; 19 | } 20 | 21 | export default BlockQuoteService; 22 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/index.js: -------------------------------------------------------------------------------- 1 | import BulletListService from './BulletListService/BulletListService'; 2 | import OrderedListService from './OrderedListService/OrderedListService'; 3 | import JoinUpService from './JoinUpService/JoinUpService'; 4 | import LiftService from './LiftService/LiftService'; 5 | import ListItemService from './ListItemService/ListItemService'; 6 | import BlockQuoteService from './BlockQuoteService/BlockQuoteService'; 7 | import ListToolGroupService from './ListToolGroupService/ListToolGroupService'; 8 | 9 | export default [ 10 | new BlockQuoteService(), 11 | new ListItemService(), 12 | new BulletListService(), 13 | new OrderedListService(), 14 | new JoinUpService(), 15 | new LiftService(), 16 | new ListToolGroupService(), 17 | ]; 18 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/components/QuestionComponent.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { WaxContext } from 'wax-prosemirror-core'; 3 | import EditorComponent from './EditorComponent'; 4 | 5 | export default ({ node, view, getPos }) => { 6 | const context = useContext(WaxContext); 7 | const { 8 | pmViews: { main }, 9 | } = context; 10 | 11 | const customProps = main.props.customValues; 12 | const { testMode } = customProps; 13 | 14 | const isEditable = main.props.editable(editable => { 15 | return editable; 16 | }); 17 | 18 | return ( 19 | 25 | ); 26 | }; 27 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/StrikeThroughService/schema/strikethroughMark.js: -------------------------------------------------------------------------------- 1 | const strikethroughMark = { 2 | attrs: { 3 | class: { default: 'strikethrough' }, 4 | style: { default: 'text-decoration:line-through' }, 5 | }, 6 | inclusive: false, 7 | parseDOM: [ 8 | { 9 | tag: 'span.strikethrough', 10 | getAttrs(hook, next) { 11 | Object.assign(hook, { 12 | class: hook.dom.getAttribute('class'), 13 | style: hook.dom.getAttribute('style'), 14 | }); 15 | next(); 16 | }, 17 | }, 18 | ], 19 | toDOM(hook, next) { 20 | // eslint-disable-next-line no-param-reassign 21 | hook.value = ['span', hook.node.attrs, 0]; 22 | next(); 23 | }, 24 | }; 25 | 26 | export default strikethroughMark; 27 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/EmphasisService/EmphasisService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import { toggleMark } from 'prosemirror-commands'; 3 | import emphasisMark from './schema/emphasisMark'; 4 | import Emphasis from './Emphasis'; 5 | 6 | class EmphasisService extends Service { 7 | register() { 8 | this.container.bind('Emphasis').to(Emphasis); 9 | const createMark = this.container.get('CreateMark'); 10 | const CreateShortCut = this.container.get('CreateShortCut'); 11 | 12 | createMark( 13 | { 14 | em: emphasisMark, 15 | }, 16 | { toWaxSchema: true }, 17 | ); 18 | 19 | CreateShortCut({ 20 | 'Mod-i': toggleMark(this.schema.marks.em), 21 | }); 22 | } 23 | } 24 | 25 | export default EmphasisService; 26 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/OENContainersService/OENContainersToolGroupService/OENContainersToolGroupService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import OENContainersToolGroup from './OENContainersToolGroup'; 3 | import OENAsideShortToolGroupService from '../OENAsideShortToolGroupService/OENAsideShortToolGroupService'; 4 | import OENAsideLongToolGroupService from '../OENAsideLongToolGroupService/OENAsideLongToolGroupService'; 5 | 6 | class OENContainersToolGroupService extends Service { 7 | register() { 8 | this.container.bind('OENContainersToolGroup').to(OENContainersToolGroup); 9 | } 10 | 11 | dependencies = [ 12 | new OENAsideShortToolGroupService(), 13 | new OENAsideLongToolGroupService(), 14 | ]; 15 | } 16 | 17 | export default OENContainersToolGroupService; 18 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/components/helpers/useOnClickOutside.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | // Hook 4 | const useOnClickOutside = (ref, handler) => { 5 | useEffect(() => { 6 | const listener = event => { 7 | /* Do nothing if clicking ref's element or descendent elements */ 8 | if (!ref.current || ref.current.contains(event.target)) { 9 | return; 10 | } 11 | 12 | handler(event); 13 | }; 14 | 15 | document.addEventListener('mousedown', listener); 16 | document.addEventListener('touchstart', listener); 17 | 18 | return () => { 19 | document.removeEventListener('mousedown', listener); 20 | document.removeEventListener('touchstart', listener); 21 | }; 22 | }, [ref, handler]); 23 | }; 24 | 25 | export default useOnClickOutside; 26 | -------------------------------------------------------------------------------- /wax-questions-service/src/EssayService/EssayAnswerNodeView.js: -------------------------------------------------------------------------------- 1 | import { QuestionsNodeView } from 'wax-prosemirror-core'; 2 | 3 | export default class EssayAnswerNodeView extends QuestionsNodeView { 4 | constructor( 5 | node, 6 | view, 7 | getPos, 8 | decorations, 9 | createPortal, 10 | Component, 11 | context, 12 | ) { 13 | super(node, view, getPos, decorations, createPortal, Component, context); 14 | 15 | this.node = node; 16 | this.outerView = view; 17 | this.getPos = getPos; 18 | this.context = context; 19 | } 20 | 21 | static name() { 22 | return 'essay_answer'; 23 | } 24 | 25 | stopEvent(event) { 26 | const innerView = this.context.pmViews[this.node.attrs.id]; 27 | return innerView && innerView.dom.contains(event.target); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/DisplayBlockLevel/index.js: -------------------------------------------------------------------------------- 1 | import AuthorService from './AuthorService/AuthorService'; 2 | import EpigraphPoetryService from './EpigraphPoetryService/EpigraphPoetryService'; 3 | import EpigraphProseService from './EpigraphProseService/EpigraphProseService'; 4 | import HeadingService from './HeadingService/HeadingService'; 5 | import SubTitleService from './SubTitleService/SubTitleService'; 6 | import TitleService from './TitleService/TitleService'; 7 | import DisplayToolGroupService from './DisplayToolGroupService/DisplayToolGroupService'; 8 | 9 | export default [ 10 | new AuthorService(), 11 | new EpigraphProseService(), 12 | new EpigraphPoetryService(), 13 | new HeadingService(), 14 | new SubTitleService(), 15 | new TitleService(), 16 | new DisplayToolGroupService(), 17 | ]; 18 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/UnderlineService/UnderlineService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import { toggleMark } from 'prosemirror-commands'; 3 | import underlineMark from './schema/underlineMark'; 4 | import Underline from './Underline'; 5 | 6 | class UnderlineService extends Service { 7 | register() { 8 | this.container.bind('Underline').to(Underline); 9 | const CreateShortCut = this.container.get('CreateShortCut'); 10 | const createMark = this.container.get('CreateMark'); 11 | createMark( 12 | { 13 | underline: underlineMark, 14 | }, 15 | { toWaxSchema: true }, 16 | ); 17 | CreateShortCut({ 18 | 'Mod-u': toggleMark(this.schema.marks.underline), 19 | }); 20 | } 21 | } 22 | 23 | export default UnderlineService; 24 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/schema/trueFalseSingleCorrectContainerNode.js: -------------------------------------------------------------------------------- 1 | const trueFalseSingleCorrectContainerNode = { 2 | attrs: { 3 | id: { default: '' }, 4 | class: { default: 'true-false-single-correct' }, 5 | }, 6 | group: 'block questions', 7 | atom: true, 8 | selectable: true, 9 | draggable: true, 10 | content: 'block*', 11 | parseDOM: [ 12 | { 13 | tag: 'div.true-false-single-correct', 14 | getAttrs(dom) { 15 | return { 16 | id: dom.getAttribute('id'), 17 | class: dom.getAttribute('class'), 18 | }; 19 | }, 20 | }, 21 | ], 22 | toDOM(node) { 23 | return ['div', node.attrs, 0]; 24 | }, 25 | }; 26 | 27 | export default trueFalseSingleCorrectContainerNode; 28 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/FindAndReplaceService/FindAndReplace.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { isEmpty } from 'lodash'; 3 | import { v4 as uuidv4 } from 'uuid'; 4 | import { injectable } from 'inversify'; 5 | import { Tools } from 'wax-prosemirror-core'; 6 | import FindAndReplaceTool from './components/FindAndReplaceTool'; 7 | 8 | @injectable() 9 | export default class FindAndReplace extends Tools { 10 | title = 'Find And Replace'; 11 | icon = 'findAndReplace'; 12 | name = 'find'; 13 | 14 | get enable() { 15 | return () => { 16 | return true; 17 | }; 18 | } 19 | 20 | renderTool(view) { 21 | if (isEmpty(view)) return null; 22 | 23 | return this.isDisplayed() ? ( 24 | 25 | ) : null; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BottomInfoService/CounterInfoService/CounterInfoTool.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { isEmpty } from 'lodash'; 3 | import { injectable } from 'inversify'; 4 | import { Tools } from 'wax-prosemirror-core'; 5 | import EditorInfoTool from './components/EditorInfoTool'; 6 | 7 | @injectable() 8 | class CounterInfoTool extends Tools { 9 | title = 'Counter Info'; 10 | name = 'CounterInfo'; 11 | 12 | get run() { 13 | return () => true; 14 | } 15 | 16 | get enable() { 17 | return () => { 18 | return true; 19 | }; 20 | } 21 | 22 | renderTool(view) { 23 | if (isEmpty(view)) return null; 24 | return this.isDisplayed() ? ( 25 | 26 | ) : null; 27 | } 28 | } 29 | 30 | export default CounterInfoTool; 31 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/CodeService/Code.js: -------------------------------------------------------------------------------- 1 | import { toggleMark } from 'prosemirror-commands'; 2 | import { injectable } from 'inversify'; 3 | import { Commands, Tools } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | export default class Code extends Tools { 7 | title = 'Toggle code'; 8 | icon = 'code'; 9 | name = 'Code'; 10 | 11 | get run() { 12 | return (state, dispatch) => { 13 | toggleMark(state.config.schema.marks.code)(state, dispatch); 14 | }; 15 | } 16 | 17 | select = state => { 18 | const { 19 | selection: { from }, 20 | } = state; 21 | if (from === null) return false; 22 | return true; 23 | }; 24 | 25 | get active() { 26 | return state => { 27 | return Commands.markActive(state.config.schema.marks.code)(state); 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /wax-questions-service/src/NumericalAnswerService/NumericalAnswerContainerNodeView.js: -------------------------------------------------------------------------------- 1 | import { QuestionsNodeView } from 'wax-prosemirror-core'; 2 | 3 | export default class NumericalAnswerContainerNodeView extends QuestionsNodeView { 4 | constructor( 5 | node, 6 | view, 7 | getPos, 8 | decorations, 9 | createPortal, 10 | Component, 11 | context, 12 | ) { 13 | super(node, view, getPos, decorations, createPortal, Component, context); 14 | 15 | this.node = node; 16 | this.outerView = view; 17 | this.getPos = getPos; 18 | this.context = context; 19 | } 20 | 21 | static name() { 22 | return 'numerical_answer_container'; 23 | } 24 | 25 | selectNode() { 26 | this.context.pmViews[this.node.attrs.id].focus(); 27 | } 28 | 29 | stopEvent(event) { 30 | return true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/StrongService/Strong.js: -------------------------------------------------------------------------------- 1 | import { toggleMark } from 'prosemirror-commands'; 2 | import { injectable } from 'inversify'; 3 | import { Commands, Tools } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | export default class Strong extends Tools { 7 | title = 'Toggle strong'; 8 | icon = 'bold'; 9 | name = 'Strong'; 10 | 11 | get run() { 12 | return (state, dispatch) => { 13 | toggleMark(state.config.schema.marks.strong)(state, dispatch); 14 | }; 15 | } 16 | 17 | select = state => { 18 | const { 19 | selection: { from }, 20 | } = state; 21 | if (from === null) return false; 22 | return true; 23 | }; 24 | 25 | get active() { 26 | return state => { 27 | return Commands.markActive(state.config.schema.marks.strong)(state); 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/FindAndReplaceService/FindAndReplaceService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import FindAndReplacePlugin from './plugins/FindAndReplacePlugin'; 3 | import FindAndReplace from './FindAndReplace'; 4 | import './findAndReplace.css'; 5 | import FindAndReplaceToolGroupService from './FindAndReplaceToolGroupService/FindAndReplaceToolGroupService'; 6 | 7 | class FindAndReplaceService extends Service { 8 | name = 'FindAndReplaceService'; 9 | 10 | boot() { 11 | this.app.PmPlugins.add( 12 | 'findAndReplacePlugin', 13 | FindAndReplacePlugin('findAndReplacePlugin'), 14 | ); 15 | } 16 | 17 | register() { 18 | this.container.bind('FindAndReplace').to(FindAndReplace); 19 | } 20 | 21 | dependencies = [new FindAndReplaceToolGroupService()]; 22 | } 23 | export default FindAndReplaceService; 24 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/EmphasisService/Emphasis.js: -------------------------------------------------------------------------------- 1 | import { toggleMark } from 'prosemirror-commands'; 2 | import { injectable } from 'inversify'; 3 | import { Commands, Tools } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | export default class Emphasis extends Tools { 7 | title = 'Toggle emphasis'; 8 | icon = 'italic'; 9 | name = 'Emphasis'; 10 | 11 | get run() { 12 | return (state, dispatch) => { 13 | toggleMark(state.config.schema.marks.em)(state, dispatch); 14 | }; 15 | } 16 | 17 | select = state => { 18 | const { 19 | selection: { from }, 20 | } = state; 21 | if (from === null) return false; 22 | return true; 23 | }; 24 | 25 | get active() { 26 | return state => { 27 | return Commands.markActive(state.config.schema.marks.em)(state); 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/SpecialCharactersService/SpecialCharactersTool.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { isEmpty } from 'lodash'; 3 | import { v4 as uuidv4 } from 'uuid'; 4 | import { injectable } from 'inversify'; 5 | import { Tools } from 'wax-prosemirror-core'; 6 | import SpecialCharactersTool from './components/SpecialCharactersTool'; 7 | 8 | @injectable() 9 | export default class SpecialCharacters extends Tools { 10 | title = 'Special Characters'; 11 | icon = 'specialCharacters'; 12 | name = 'specialCharacters'; 13 | 14 | get enable() { 15 | return () => { 16 | return true; 17 | }; 18 | } 19 | 20 | renderTool(view) { 21 | if (isEmpty(view)) return null; 22 | 23 | return this.isDisplayed() ? ( 24 | 25 | ) : null; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.gitlab/issue_templates/Feature Request.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Context 4 | 5 | 6 | 7 | ## Proposal 8 | 9 | 10 | 11 | ## Design 12 | 13 | 14 | 15 | ## Implementation (if applicable) 16 | 17 | 18 | 19 | ## Alternative approaches (if applicable) 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultConfig.js: -------------------------------------------------------------------------------- 1 | import SchemaService from './defaultServices/SchemaService/SchemaService'; 2 | import RulesService from './defaultServices/RulesService/RulesService'; 3 | import ShortCutsService from './defaultServices/ShortCutsService/ShortCutsService'; 4 | import LayoutService from './defaultServices/LayoutService/LayoutService'; 5 | import PortalService from './defaultServices/PortalService/PortalService'; 6 | import MenuService from './defaultServices/MenuService/MenuService'; 7 | import OverlayService from './defaultServices/OverlayService/OverlayService'; 8 | 9 | export default () => ({ 10 | services: [ 11 | new SchemaService(), 12 | new RulesService(), 13 | new ShortCutsService(), 14 | new LayoutService(), 15 | new PortalService(), 16 | new MenuService(), 17 | new OverlayService(), 18 | ], 19 | }); 20 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/MathService/InlineInputRule.js: -------------------------------------------------------------------------------- 1 | import { InputRule } from 'prosemirror-inputrules'; 2 | 3 | const inlineInputRule = (pattern, nodeType, getAttrs) => { 4 | return new InputRule(pattern, (state, match, start, end) => { 5 | const $start = state.doc.resolve(start); 6 | const index = $start.index(); 7 | const $end = state.doc.resolve(end); 8 | // get attrs 9 | const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs; 10 | // check if replacement valid 11 | if (!$start.parent.canReplaceWith(index, $end.index(), nodeType)) { 12 | return null; 13 | } 14 | // perform replacement 15 | return state.tr.replaceRangeWith( 16 | start, 17 | end, 18 | nodeType.create(attrs, nodeType.schema.text(match[1])), 19 | ); 20 | }); 21 | }; 22 | 23 | export default inlineInputRule; 24 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleDropDownService/schema/multipleDropDownContainerNode.js: -------------------------------------------------------------------------------- 1 | const multipleDropDownContainerNode = { 2 | attrs: { 3 | id: { default: '' }, 4 | class: { default: 'multiple-drop-down-container' }, 5 | feedback: { default: '' }, 6 | }, 7 | group: 'block questions', 8 | isolating: true, 9 | // content: 'paragraph* bulletlist* orderedlist*', 10 | content: 'block*', 11 | parseDOM: [ 12 | { 13 | tag: 'div.multiple-drop-down-container', 14 | getAttrs(dom) { 15 | return { 16 | id: dom.getAttribute('id'), 17 | class: dom.getAttribute('class'), 18 | feedback: dom.getAttribute('feedback'), 19 | }; 20 | }, 21 | }, 22 | ], 23 | toDOM(node) { 24 | return ['div', node.attrs, 0]; 25 | }, 26 | }; 27 | 28 | export default multipleDropDownContainerNode; 29 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CodeBlockService/CodeBlockService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import codeBlockNode from './schema/codeBlockNode'; 3 | import highlightPlugin from './plugins/highlightPlugin'; 4 | import CodeBlockTool from './CodeBlockTool'; 5 | import CodeBlockToolGroupService from './CodeBlockToolGroupService/CodeBlockToolGroupService'; 6 | import './highlightStyles.css'; 7 | 8 | export default class CodeBlockService extends Service { 9 | boot() { 10 | this.app.PmPlugins.add('highlightPlugin', highlightPlugin()); 11 | } 12 | 13 | register() { 14 | this.container.bind('CodeBlockTool').to(CodeBlockTool); 15 | const createNode = this.container.get('CreateNode'); 16 | 17 | createNode({ 18 | code_block: codeBlockNode, 19 | }); 20 | } 21 | 22 | dependencies = [new CodeBlockToolGroupService()]; 23 | } 24 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/NoteService/NoteService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import footNoteNode from './schema/footNoteNode'; 3 | import Note from './Note'; 4 | import NoteComponent from './NoteComponent'; 5 | import NoteToolGroupService from './NoteToolGroupService/NoteToolGroupService'; 6 | import './note.css'; 7 | 8 | class NoteService extends Service { 9 | name = 'NoteService'; 10 | 11 | boot() { 12 | const layout = this.container.get('Layout'); 13 | layout.addComponent('notesArea', NoteComponent); 14 | } 15 | 16 | register() { 17 | const createNode = this.container.get('CreateNode'); 18 | this.container.bind('Note').to(Note); 19 | 20 | createNode({ 21 | footnote: footNoteNode, 22 | }); 23 | } 24 | 25 | dependencies = [new NoteToolGroupService()]; 26 | } 27 | 28 | export default NoteService; 29 | -------------------------------------------------------------------------------- /.gitlab/issue_templates/bug-report.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Expected behaviour 4 | 5 | 6 | 7 | ## Current behaviour 8 | 9 | 10 | 11 | ## Steps to reproduce 12 | 13 | 14 | 15 | 1. 16 | 2. 17 | 3. 18 | 4. 19 | 20 | ## Environment 21 | 22 | 23 | 24 | ## Possible solution 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ModalService/ModalService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import ModalPlugin from './pmPlugins/ModalPlugin'; 3 | import ModalComponent from './ModalComponent'; 4 | const PLUGIN_KEY = 'overlay'; 5 | 6 | export default class ModalService extends Service { 7 | boot() { 8 | this.app.PmPlugins.add(PLUGIN_KEY, ModalPlugin(PLUGIN_KEY)); 9 | } 10 | register() { 11 | this.container.bind('CreateModal').toFactory(context => { 12 | return (Component, pluginName) => { 13 | const PmPlugins = context.container.get('PmPlugins'); 14 | const plugin = PmPlugins.get(pluginName); 15 | const layout = context.container.get('Layout'); 16 | layout.addComponent( 17 | 'editorOverlays', 18 | ModalComponent(Component, plugin), 19 | ); 20 | }; 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/SmallCapsService/SmallCaps.js: -------------------------------------------------------------------------------- 1 | import { toggleMark } from 'prosemirror-commands'; 2 | import { injectable } from 'inversify'; 3 | import { Commands, Tools } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | export default class SmallCaps extends Tools { 7 | title = 'Toggle Small Caps'; 8 | icon = 'smallCaps'; 9 | name = 'SmallCaps'; 10 | 11 | get run() { 12 | return (state, dispatch) => { 13 | toggleMark(state.config.schema.marks.smallcaps)(state, dispatch); 14 | }; 15 | } 16 | 17 | select = state => { 18 | const { 19 | selection: { from }, 20 | } = state; 21 | if (from === null) return false; 22 | return true; 23 | }; 24 | 25 | get active() { 26 | return state => { 27 | return Commands.markActive(state.config.schema.marks.smallcaps)(state); 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/SubscriptService/Subscript.js: -------------------------------------------------------------------------------- 1 | import { toggleMark } from 'prosemirror-commands'; 2 | import { injectable } from 'inversify'; 3 | import { Commands, Tools } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | export default class Subscript extends Tools { 7 | title = 'Toggle subscript'; 8 | icon = 'subscript'; 9 | name = 'Subscript'; 10 | 11 | get run() { 12 | return (state, dispatch) => { 13 | toggleMark(state.config.schema.marks.subscript)(state, dispatch); 14 | }; 15 | } 16 | 17 | select = state => { 18 | const { 19 | selection: { from }, 20 | } = state; 21 | if (from === null) return false; 22 | return true; 23 | }; 24 | 25 | get active() { 26 | return state => { 27 | return Commands.markActive(state.config.schema.marks.subscript)(state); 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/OENContainersService/OENAsideLongToolGroupService/OENAsideLongToolGroup.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { injectable, inject } from 'inversify'; 3 | import { ToolGroup, LeftMenuTitle } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | class OENAsideLongToolGroup extends ToolGroup { 7 | tools = []; 8 | title = (); 9 | 10 | constructor( 11 | @inject('OENAsideLongToolCaseStudy') OENAsideLongToolCaseStudy, 12 | @inject('OENAsideLongToolBiography') OENAsideLongToolBiography, 13 | @inject('OENAsideLongToolWorkedExample') OENAsideLongToolWorkedExample, 14 | ) { 15 | super(); 16 | this.tools = [ 17 | OENAsideLongToolCaseStudy, 18 | OENAsideLongToolBiography, 19 | OENAsideLongToolWorkedExample, 20 | ]; 21 | } 22 | } 23 | 24 | export default OENAsideLongToolGroup; 25 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/FullScreenService/FullScreenTool.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { isEmpty } from 'lodash'; 3 | import { injectable } from 'inversify'; 4 | import { Tools } from 'wax-prosemirror-core'; 5 | import FullScreenButton from './components/FullScreenButton'; 6 | 7 | @injectable() 8 | export default class FullScreenTool extends Tools { 9 | title = 'Full screen'; 10 | icon = 'fullScreen'; 11 | name = 'FullScreen'; 12 | 13 | get run() { 14 | return () => true; 15 | } 16 | 17 | select = () => { 18 | return true; 19 | }; 20 | 21 | get enable() { 22 | return () => { 23 | return true; 24 | }; 25 | } 26 | 27 | renderTool(view) { 28 | if (isEmpty(view)) return null; 29 | return this.isDisplayed() ? ( 30 | 31 | ) : null; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/MathService/BlockInputRule.js: -------------------------------------------------------------------------------- 1 | import { InputRule } from 'prosemirror-inputrules'; 2 | import { NodeSelection } from 'prosemirror-state'; 3 | 4 | const blockInputRule = (pattern, nodeType, getAttrs) => { 5 | return new InputRule(pattern, (state, match, start, end) => { 6 | const $start = state.doc.resolve(start); 7 | const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs; 8 | 9 | if ( 10 | !$start 11 | .node(-1) 12 | .canReplaceWith($start.index(-1), $start.indexAfter(-1), nodeType) 13 | ) 14 | return null; 15 | 16 | const tr = state.tr 17 | .delete(start, end) 18 | .setBlockType(start, start, nodeType, attrs); 19 | return tr.setSelection( 20 | NodeSelection.create(tr.doc, tr.mapping.map($start.pos - 1)), 21 | ); 22 | }); 23 | }; 24 | export default blockInputRule; 25 | -------------------------------------------------------------------------------- /editors/demo/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | // import ReactDOM from 'react-dom/client'; 3 | import ReactDOM from 'react-dom'; 4 | import Editors from './Editors'; 5 | import * as serviceWorker from './serviceWorker'; 6 | import '../../../wax-prosemirror-core/dist/index.css'; 7 | import '../../../wax-prosemirror-services/dist/index.css'; 8 | import '../../../wax-questions-service/dist/index.css'; 9 | import '../../../wax-table-service/dist/index.css'; 10 | // const root = ReactDOM.createRoot(document.getElementById('root')); 11 | // root.render(); 12 | 13 | ReactDOM.render(, document.getElementById('root')); 14 | 15 | // If you want your app to work offline and load faster, you can change 16 | // unregister() to register() below. Note this comes with some pitfalls. 17 | // Learn more about service workers: https://bit.ly/CRA-PWA 18 | serviceWorker.unregister(); 19 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/SuperscriptService/Superscript.js: -------------------------------------------------------------------------------- 1 | import { toggleMark } from 'prosemirror-commands'; 2 | import { injectable } from 'inversify'; 3 | import { Commands, Tools } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | export default class Superscript extends Tools { 7 | title = 'Toggle superscript'; 8 | icon = 'superscript'; 9 | name = 'Superscript'; 10 | 11 | get run() { 12 | return (state, dispatch) => { 13 | toggleMark(state.config.schema.marks.superscript)(state, dispatch); 14 | }; 15 | } 16 | 17 | select = state => { 18 | const { 19 | selection: { from }, 20 | } = state; 21 | if (from === null) return false; 22 | return true; 23 | }; 24 | 25 | get active() { 26 | return state => { 27 | return Commands.markActive(state.config.schema.marks.superscript)(state); 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /wax-questions-service/src/EssayService/components/EssayQuestionComponent.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { WaxContext } from 'wax-prosemirror-core'; 3 | import EditorComponent from '../../MultipleChoiceQuestionService/components/EditorComponent'; 4 | 5 | export default ({ node, view, getPos }) => { 6 | const context = useContext(WaxContext); 7 | const { 8 | pmViews: { main }, 9 | } = context; 10 | 11 | const customProps = main.props.customValues; 12 | const { testMode } = customProps; 13 | 14 | const isEditable = main.props.editable(editable => { 15 | return editable; 16 | }); 17 | return ( 18 | 26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/Config.js: -------------------------------------------------------------------------------- 1 | import { set, get, isArrayLikeObject } from 'lodash'; 2 | import { injectable, inject } from 'inversify'; 3 | 4 | @injectable() 5 | export default class Config { 6 | _config = {}; 7 | constructor(@inject('config') config) { 8 | this._config = config; 9 | } 10 | 11 | set(key, value) { 12 | set(this._config, key, value); 13 | return this._config; 14 | } 15 | 16 | get(key) { 17 | return get(this._config, key); 18 | } 19 | 20 | pushToArray(key, value) { 21 | let oldValue = this.get(key); 22 | if (oldValue) { 23 | if (isArrayLikeObject(value)) { 24 | value.forEach(v => { 25 | oldValue.push(v); 26 | }); 27 | } else { 28 | oldValue.push(value); 29 | } 30 | } else { 31 | oldValue = value; 32 | } 33 | this.set(key, oldValue); 34 | return this; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/ListItemService/schema/listItemNode.js: -------------------------------------------------------------------------------- 1 | import { SchemaHelpers } from 'wax-prosemirror-core'; 2 | 3 | const listItemNode = { 4 | content: 'paragraph block*', 5 | attrs: { 6 | track: { default: [] }, 7 | }, 8 | parseDOM: [ 9 | { 10 | tag: 'li', 11 | getAttrs(hook, next) { 12 | Object.assign(hook, { 13 | track: SchemaHelpers.parseTracks(hook.dom.dataset.track), 14 | }); 15 | next(); 16 | }, 17 | }, 18 | ], 19 | toDOM(hook, next) { 20 | const attrs = {}; 21 | if (hook.node.attrs.track && hook.node.attrs.track.length) { 22 | attrs['data-track'] = JSON.stringify(hook.node.attrs.track); 23 | } 24 | // eslint-disable-next-line no-param-reassign 25 | hook.value = ['li', attrs, 0]; 26 | next(); 27 | }, 28 | defining: true, 29 | }; 30 | 31 | export default listItemNode; 32 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/OENContainersService/schema/OenContainerNode.js: -------------------------------------------------------------------------------- 1 | const OenContainerNode = { 2 | content: 'block+', 3 | group: 'block', 4 | attrs: { 5 | id: { default: '' }, 6 | class: { default: '' }, 7 | type: { default: 'content_structure_element' }, 8 | }, 9 | defining: true, 10 | parseDOM: [ 11 | { 12 | tag: 'div[data-type="content_structure_element"]', 13 | getAttrs(dom) { 14 | return { 15 | id: dom.getAttribute('id'), 16 | class: dom.getAttribute('class'), 17 | type: dom.dataset.type, 18 | }; 19 | }, 20 | }, 21 | ], 22 | toDOM(node) { 23 | return [ 24 | 'div', 25 | { 26 | id: node.attrs.id, 27 | class: node.attrs.class, 28 | 'data-type': node.attrs.type, 29 | }, 30 | 0, 31 | ]; 32 | }, 33 | }; 34 | 35 | export default OenContainerNode; 36 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/TextBlockLevel/TextToolGroupService/Text.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { injectable, inject } from 'inversify'; 3 | import { ToolGroup, LeftMenuTitle } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | class Text extends ToolGroup { 7 | tools = []; 8 | title = (); 9 | 10 | constructor( 11 | @inject('Paragraph') paragraph, 12 | @inject('ParagraphContinued') paragraphContinued, 13 | @inject('ExtractProse') extractProse, 14 | @inject('ExtractPoetry') extractPoetry, 15 | @inject('SourceNote') sourceNote, 16 | // @inject('BlockQuote') blockQuote, 17 | ) { 18 | super(); 19 | this.tools = [ 20 | paragraph, 21 | paragraphContinued, 22 | extractProse, 23 | extractPoetry, 24 | sourceNote, 25 | // blockQuote, 26 | ]; 27 | } 28 | } 29 | 30 | export default Text; 31 | -------------------------------------------------------------------------------- /editors/demo/src/NCBI/config/configMini.js: -------------------------------------------------------------------------------- 1 | import { DefaultSchema } from 'wax-prosemirror-core'; 2 | import { 3 | InlineAnnotationsService, 4 | ListsService, 5 | BaseService, 6 | LinkService, 7 | } from 'wax-prosemirror-services'; 8 | 9 | const config = { 10 | MenuService: [ 11 | { 12 | templateArea: 'topBar', 13 | toolGroups: [ 14 | 'Base', 15 | { 16 | name: 'Annotations', 17 | exclude: ['Code', 'StrikeThrough', 'Underline', 'SmallCaps'], 18 | }, 19 | 'Lists', 20 | ], 21 | }, 22 | ], 23 | 24 | RulesService: [], 25 | ShortCutsService: {}, 26 | LinkService: {}, 27 | SchemaService: DefaultSchema, 28 | PmPlugins: [], 29 | 30 | services: [ 31 | new InlineAnnotationsService(), 32 | new LinkService(), 33 | new BaseService(), 34 | new ListsService(), 35 | ], 36 | }; 37 | 38 | export default config; 39 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/BulletListService/schema/bulletListNode.js: -------------------------------------------------------------------------------- 1 | import { SchemaHelpers } from 'wax-prosemirror-core'; 2 | 3 | const bulletListNode = { 4 | group: 'block', 5 | content: 'list_item+', 6 | attrs: { 7 | track: { default: [] }, 8 | }, 9 | parseDOM: [ 10 | { 11 | tag: 'ul', 12 | getAttrs(hook, next) { 13 | Object.assign(hook, { 14 | track: SchemaHelpers.parseTracks(hook.dom.dataset.track), 15 | }); 16 | next(); 17 | }, 18 | }, 19 | ], 20 | toDOM(hook, next) { 21 | const attrs = {}; 22 | if (hook.node.attrs.track && hook.node.attrs.track.length) { 23 | attrs['data-track'] = JSON.stringify(hook.node.attrs.track); 24 | } 25 | // eslint-disable-next-line no-param-reassign 26 | hook.value = ['ul', attrs, 0]; 27 | next(); 28 | }, 29 | }; 30 | 31 | export default bulletListNode; 32 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/CustomTagBlockService/schema/customBlockNode.js: -------------------------------------------------------------------------------- 1 | const customBlockNode = { 2 | content: 'inline*', 3 | group: 'block', 4 | priority: 0, 5 | defining: true, 6 | attrs: { 7 | class: { default: '' }, 8 | type: { default: 'block' }, 9 | }, 10 | parseDOM: [ 11 | { 12 | tag: 'p[data-type="block"]', 13 | getAttrs(hook, next) { 14 | Object.assign(hook, { 15 | class: hook.dom.getAttribute('class'), 16 | type: hook.dom.dataset.type, 17 | }); 18 | next(); 19 | }, 20 | }, 21 | ], 22 | toDOM(hook, next) { 23 | const attrs = { 24 | class: hook.node.attrs.class, 25 | 'data-type': hook.node.attrs.type, 26 | }; 27 | // eslint-disable-next-line no-param-reassign 28 | hook.value = ['p', attrs, 0]; 29 | next(); 30 | }, 31 | }; 32 | 33 | export default customBlockNode; 34 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/UnderlineService/Underline.js: -------------------------------------------------------------------------------- 1 | import { toggleMark } from 'prosemirror-commands'; 2 | import { injectable } from 'inversify'; 3 | import { Commands, Tools } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | export default class Underline extends Tools { 7 | title = 'Toggle underline'; 8 | // content = icons.underline; 9 | icon = 'underline'; 10 | name = 'Underline'; 11 | 12 | get run() { 13 | return (state, dispatch) => { 14 | toggleMark(state.config.schema.marks.underline)(state, dispatch); 15 | }; 16 | } 17 | 18 | select = state => { 19 | const { 20 | selection: { from }, 21 | } = state; 22 | if (from === null) return false; 23 | return true; 24 | }; 25 | 26 | get active() { 27 | return state => { 28 | return Commands.markActive(state.config.schema.marks.underline)(state); 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BottomInfoService/ShortCutsInfoService/ShortCutsInfoTool.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { isEmpty } from 'lodash'; 3 | import { injectable } from 'inversify'; 4 | import { Tools } from 'wax-prosemirror-core'; 5 | import EditorShortCutsTool from './components/EditorShortCutsTool'; 6 | 7 | @injectable() 8 | class ShortCutsInfoTool extends Tools { 9 | title = 'ShortCuts Info'; 10 | name = 'ShortCutsInfo'; 11 | 12 | get run() { 13 | return () => true; 14 | } 15 | 16 | get enable() { 17 | return () => { 18 | return true; 19 | }; 20 | } 21 | 22 | renderTool(view) { 23 | if (isEmpty(view)) return null; 24 | return this.isDisplayed() ? ( 25 | 30 | ) : null; 31 | } 32 | } 33 | 34 | export default ShortCutsInfoTool; 35 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CodeBlockService/CodeBlockTool.js: -------------------------------------------------------------------------------- 1 | import { injectable } from 'inversify'; 2 | import { setBlockType } from 'prosemirror-commands'; 3 | import { Tools } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | class CodeBlockTool extends Tools { 7 | title = 'Insert Code Block'; 8 | icon = 'codeBlock'; 9 | name = 'CodeBlockTool'; 10 | 11 | get run() { 12 | return (state, dispatch) => { 13 | setBlockType(state.config.schema.nodes.code_block)(state, dispatch); 14 | }; 15 | } 16 | 17 | select = (state, activeViewId, activeView) => { 18 | const { disallowedTools } = activeView.props; 19 | if (disallowedTools.includes('CodeBlock')) return false; 20 | return true; 21 | }; 22 | 23 | get enable() { 24 | return state => { 25 | return setBlockType(state.config.schema.nodes.code_block)(state); 26 | }; 27 | } 28 | } 29 | 30 | export default CodeBlockTool; 31 | -------------------------------------------------------------------------------- /wax-questions-service/src/EssayService/EssayPromptNodeView.js: -------------------------------------------------------------------------------- 1 | import { QuestionsNodeView } from 'wax-prosemirror-core'; 2 | 3 | export default class EssayPromptNodeView extends QuestionsNodeView { 4 | constructor( 5 | node, 6 | view, 7 | getPos, 8 | decorations, 9 | createPortal, 10 | Component, 11 | context, 12 | ) { 13 | super(node, view, getPos, decorations, createPortal, Component, context); 14 | 15 | this.node = node; 16 | this.outerView = view; 17 | this.getPos = getPos; 18 | this.context = context; 19 | } 20 | 21 | static name() { 22 | return 'essay_prompt'; 23 | } 24 | 25 | stopEvent(event) { 26 | if (event.target.type === 'text' || event.target.type === 'textarea') { 27 | return true; 28 | } 29 | const innerView = this.context.pmViews[this.node.attrs.id]; 30 | return innerView && innerView.dom.contains(event.target); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # include: 2 | # - project: 'cokoapps/ci' 3 | # ref: main 4 | # file: 'ci-templates.yml' 5 | 6 | variables: 7 | IMAGE_NAME_DEMO: $CI_REGISTRY/wax/wax-prosemirror/wax-demo 8 | BUILD_PATH: . 9 | 10 | stages: 11 | - Build 12 | - Deploy 13 | 14 | build demo: 15 | stage: Build 16 | image: docker:26 17 | services: 18 | - docker:26-dind 19 | before_script: 20 | - echo "$CI_REGISTRY_PASSWORD" | docker login "$CI_REGISTRY" -u "$CI_REGISTRY_USER" --password-stdin 21 | script: 22 | - docker build --tag $IMAGE_NAME_DEMO:$CI_COMMIT_SHA -f $BUILD_PATH/Dockerfile-production $BUILD_PATH 23 | - docker push $IMAGE_NAME_DEMO:$CI_COMMIT_SHA 24 | only: 25 | - master 26 | 27 | pages: 28 | stage: Deploy 29 | image: $IMAGE_NAME_DEMO:$CI_COMMIT_SHA 30 | script: 31 | - cp -r /home/wax/_build public 32 | artifacts: 33 | paths: 34 | - public 35 | only: 36 | - master 37 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/LinkService/schema/linkMark.js: -------------------------------------------------------------------------------- 1 | const linkMark = { 2 | attrs: { 3 | href: { default: null }, 4 | rel: { default: '' }, 5 | target: { default: 'blank' }, 6 | title: { default: null }, 7 | }, 8 | excludes: 'link', 9 | inclusive: false, 10 | parseDOM: [ 11 | { 12 | tag: 'a[href]', 13 | getAttrs(hook, next) { 14 | const href = hook.dom.getAttribute('href'); 15 | const target = href && href.indexOf('#') === 0 ? '' : 'blank'; 16 | Object.assign(hook, { 17 | href: hook.dom.getAttribute('href'), 18 | title: hook.dom.getAttribute('title'), 19 | target, 20 | }); 21 | next(); 22 | }, 23 | }, 24 | ], 25 | toDOM(hook, next) { 26 | // eslint-disable-next-line no-param-reassign 27 | hook.value = ['a', hook.node.attrs, 0]; 28 | next(); 29 | }, 30 | }; 31 | 32 | export default linkMark; 33 | -------------------------------------------------------------------------------- /wax-questions-service/src/EssayService/EssayQuestionNodeView.js: -------------------------------------------------------------------------------- 1 | import { QuestionsNodeView } from 'wax-prosemirror-core'; 2 | 3 | export default class EssayQuestionNodeView extends QuestionsNodeView { 4 | constructor( 5 | node, 6 | view, 7 | getPos, 8 | decorations, 9 | createPortal, 10 | Component, 11 | context, 12 | ) { 13 | super(node, view, getPos, decorations, createPortal, Component, context); 14 | 15 | this.node = node; 16 | this.outerView = view; 17 | this.getPos = getPos; 18 | this.context = context; 19 | } 20 | 21 | static name() { 22 | return 'essay_question'; 23 | } 24 | 25 | stopEvent(event) { 26 | if (event.target.type === 'text' || event.target.type === 'textarea') { 27 | return true; 28 | } 29 | const innerView = this.context.pmViews[this.node.attrs.id]; 30 | return innerView && innerView.dom.contains(event.target); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/StrikeThroughService/StrikeThrough.js: -------------------------------------------------------------------------------- 1 | import { toggleMark } from 'prosemirror-commands'; 2 | import { injectable } from 'inversify'; 3 | import { Commands, Tools } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | export default class StrikeThrough extends Tools { 7 | title = 'Toggle strikethrough'; 8 | icon = 'strikethrough'; 9 | name = 'StrikeThrough'; 10 | 11 | get run() { 12 | return (state, dispatch) => { 13 | toggleMark(state.config.schema.marks.strikethrough)(state, dispatch); 14 | }; 15 | } 16 | 17 | select = state => { 18 | const { 19 | selection: { from }, 20 | } = state; 21 | if (from === null) return false; 22 | return true; 23 | }; 24 | 25 | get active() { 26 | return state => { 27 | return Commands.markActive(state.config.schema.marks.strikethrough)( 28 | state, 29 | ); 30 | }; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /wax-questions-service/src/MatchingService/MatchingOptionNodeView.js: -------------------------------------------------------------------------------- 1 | import { QuestionsNodeView } from 'wax-prosemirror-core'; 2 | 3 | export default class MatchingOptionNodeView extends QuestionsNodeView { 4 | constructor( 5 | node, 6 | view, 7 | getPos, 8 | decorations, 9 | createPortal, 10 | Component, 11 | context, 12 | ) { 13 | super(node, view, getPos, decorations, createPortal, Component, context); 14 | 15 | this.node = node; 16 | this.outerView = view; 17 | this.getPos = getPos; 18 | this.context = context; 19 | } 20 | 21 | static name() { 22 | return 'matching_option'; 23 | } 24 | 25 | stopEvent(event) { 26 | if (event.target.type === 'text' || event.target.type === 'button') { 27 | return true; 28 | } 29 | const innerView = this.context.pmViews[this.node.attrs.id]; 30 | return innerView && innerView.dom.contains(event.target); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

Wax Editor

3 |
4 | 5 | | [![MIT license](https://img.shields.io/badge/license-MIT-e51879.svg)](https://gitlab.coko.foundation/wax/wax-prosemirror/raw/master/LICENSE) | 6 | | :------------------------------------------------------------------------------------------------------------------------------------------: | 7 | 8 | 9 | Wax Editor is built on top of the Prosemirror library. Check Prosemirror [website](https://prosemirror.net/) and [GitHub repo](https://github.com/ProseMirror) for more information. 10 | 11 | ## [Various Demos.](https://demo.waxjs.net/) 12 | 13 | 14 | ## Get up and running 15 | 16 | Run a local version of the demos 17 | 18 | 1. `yarn with node >= 14` 19 | 20 | 2. `yarn build` 21 | 22 | 3. `yarn start` Will bring up a demos of different ediitors 23 | 24 | ## Documentation 25 | 26 | Documentation can be found [here](https://waxjs.net/docs/wax/). 27 | -------------------------------------------------------------------------------- /wax-citation-service/README.md: -------------------------------------------------------------------------------- 1 | ## Wax citation package 2 | 3 | Wax Citation Package 4 | 5 | ## How to use 6 | 7 | ### Editor's config 8 | 9 | ``` 10 | import { TablesService, tableEditing, columnResizing } from 'wax-table-service'; 11 | ``` 12 | 13 | ### Styles(preferably in your layout) 14 | 15 | ``` 16 | import 'wax-table-service/dist/index.css' 17 | ``` 18 | 19 | ### Tools 20 | 21 | ``` 22 | MenuService: [ 23 | { 24 | templateArea: 'mainMenuToolBar', 25 | toolGroups: [ 26 | 'Tables', 27 | ], 28 | }, 29 | ], 30 | 31 | ``` 32 | 33 | ### ProseMirror Plugins 34 | 35 | In case you need tableEditing or columnResizing plugins add the to the array of `PmPlugins` in your editor's config 36 | 37 | ``` 38 | PmPlugins: [ 39 | tableEditing(), 40 | columnResizing(), 41 | ], 42 | ``` 43 | 44 | ### Start the Service 45 | 46 | ``` 47 | services: [ 48 | new TablesService(), 49 | ] 50 | ``` 51 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/utilities/schema/DefaultSchema.js: -------------------------------------------------------------------------------- 1 | export default { 2 | nodes: { 3 | doc: { 4 | content: 'block+', 5 | }, 6 | text: { 7 | group: 'inline', 8 | }, 9 | hard_break: { 10 | inline: true, 11 | group: 'inline', 12 | selectable: false, 13 | parseDOM: [{ tag: 'br' }], 14 | toDOM() { 15 | return ['br']; 16 | }, 17 | }, 18 | paragraph: { 19 | group: 'block', 20 | content: 'inline*', 21 | attrs: { 22 | class: { default: 'paragraph' }, 23 | }, 24 | parseDOM: [ 25 | { 26 | tag: 'p.paragraph', 27 | getAttrs(dom) { 28 | return { 29 | class: dom.getAttribute('class'), 30 | }; 31 | }, 32 | }, 33 | ], 34 | toDOM(node) { 35 | return ['p', node.attrs, 0]; 36 | }, 37 | }, 38 | }, 39 | marks: {}, 40 | }; 41 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/schema/multipleChoiceSingleCorrectContainerNode.js: -------------------------------------------------------------------------------- 1 | const multipleChoiceSingleCorrectContainerNode = { 2 | attrs: { 3 | id: { default: '' }, 4 | class: { default: 'multiple-choice-single-correct' }, 5 | correctId: { default: '' }, 6 | }, 7 | group: 'block questions', 8 | atom: true, 9 | selectable: true, 10 | draggable: true, 11 | content: 'block*', 12 | parseDOM: [ 13 | { 14 | tag: 'div.multiple-choice-single-correct', 15 | getAttrs(dom) { 16 | return { 17 | id: dom.getAttribute('id'), 18 | class: dom.getAttribute('class'), 19 | correctId: dom.getAttribute('correctId'), 20 | }; 21 | }, 22 | }, 23 | ], 24 | toDOM(node) { 25 | return ['div', node.attrs, 0]; 26 | }, 27 | }; 28 | 29 | export default multipleChoiceSingleCorrectContainerNode; 30 | -------------------------------------------------------------------------------- /wax-prosemirror-core/rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from '@rollup/plugin-babel'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import external from 'rollup-plugin-peer-deps-external'; 4 | import css from 'rollup-plugin-import-css'; 5 | import { terser } from 'rollup-plugin-terser'; 6 | 7 | export default { 8 | input: './index.js', 9 | output: [ 10 | { 11 | file: 'dist/index.js', 12 | format: 'esm', 13 | sourcemap: false, 14 | }, 15 | ], 16 | plugins: [ 17 | css(), 18 | external({ 19 | includeDependencies: true, 20 | }), 21 | babel({ 22 | babelHelpers: 'runtime', 23 | presets: ['react-app'], 24 | plugins: [ 25 | ['@babel/plugin-proposal-decorators', { legacy: true }], 26 | 'babel-plugin-parameter-decorator', 27 | ], 28 | exclude: 'node_modules/**', 29 | }), 30 | commonjs(), 31 | // terser(), 32 | ], 33 | external: [], 34 | }; 35 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CommentsService/components/ui/trackChanges/HideShowTool.js: -------------------------------------------------------------------------------- 1 | /* eslint react/prop-types: 0 */ 2 | import React, { useState, useMemo } from 'react'; 3 | import { MenuButton } from 'wax-prosemirror-core'; 4 | 5 | const HideShowTool = ({ view = {}, item, enabled }) => { 6 | const [isEnabled, setEnabled] = useState(enabled); 7 | 8 | const handleMouseDown = e => { 9 | e.preventDefault(); 10 | setEnabled(!isEnabled); 11 | item.run(view.state, view.dispatch); 12 | }; 13 | 14 | const HideShowToolComponent = useMemo( 15 | () => ( 16 | handleMouseDown(e)} 21 | title={item.title} 22 | /> 23 | ), 24 | [isEnabled], 25 | ); 26 | 27 | return HideShowToolComponent; 28 | }; 29 | 30 | export default HideShowTool; 31 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/QuestionNodeView.js: -------------------------------------------------------------------------------- 1 | import { QuestionsNodeView } from 'wax-prosemirror-core'; 2 | 3 | export default class QuestionNodeView extends QuestionsNodeView { 4 | constructor( 5 | node, 6 | view, 7 | getPos, 8 | decorations, 9 | createPortal, 10 | Component, 11 | context, 12 | ) { 13 | super(node, view, getPos, decorations, createPortal, Component, context); 14 | 15 | this.node = node; 16 | this.outerView = view; 17 | this.getPos = getPos; 18 | this.context = context; 19 | } 20 | 21 | static name() { 22 | return 'question_node_multiple'; 23 | } 24 | 25 | stopEvent(event) { 26 | if (event.target.type === 'text' || event.target.type === 'textarea') { 27 | return true; 28 | } 29 | const innerView = this.context.pmViews[this.node.attrs.id]; 30 | return innerView && innerView.dom.contains(event.target); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleDropDownService/CreateDropDownService/MultipleDropDownNodeView.js: -------------------------------------------------------------------------------- 1 | import { QuestionsNodeView } from 'wax-prosemirror-core'; 2 | 3 | export default class MultipleDropDownNodeView extends QuestionsNodeView { 4 | constructor( 5 | node, 6 | view, 7 | getPos, 8 | decorations, 9 | createPortal, 10 | Component, 11 | context, 12 | ) { 13 | super(node, view, getPos, decorations, createPortal, Component, context); 14 | 15 | this.node = node; 16 | this.outerView = view; 17 | this.getPos = getPos; 18 | this.context = context; 19 | } 20 | 21 | static name() { 22 | return 'multiple_drop_down_option'; 23 | } 24 | 25 | stopEvent(event) { 26 | if (event.target.type === 'text') { 27 | return true; 28 | } 29 | const innerView = this.context.pmViews[this.node.attrs.id]; 30 | return innerView && innerView.dom.contains(event.target); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BaseService/RedoService/Redo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { isEmpty } from 'lodash'; 3 | import { redo } from 'prosemirror-history'; 4 | import { injectable } from 'inversify'; 5 | import { Tools } from 'wax-prosemirror-core'; 6 | import UndoRedoButton from '../components/UndoRedoButton'; 7 | 8 | @injectable() 9 | export default class Redo extends Tools { 10 | title = 'Redo'; 11 | icon = 'redo'; 12 | name = 'Redo'; 13 | 14 | get run() { 15 | return (state, dispatch) => { 16 | redo(state, tr => dispatch(tr.setMeta('inputType', 'Redo'))); 17 | }; 18 | } 19 | 20 | get enable() { 21 | return redo; 22 | } 23 | 24 | select(state) { 25 | return redo(state); 26 | } 27 | 28 | renderTool(view) { 29 | if (isEmpty(view)) return null; 30 | return this.isDisplayed() ? ( 31 | 32 | ) : null; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/BaseService/UndoService/Undo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { isEmpty } from 'lodash'; 3 | import { undo } from 'prosemirror-history'; 4 | import { injectable } from 'inversify'; 5 | import { Tools } from 'wax-prosemirror-core'; 6 | import UndoRedoButton from '../components/UndoRedoButton'; 7 | 8 | @injectable() 9 | export default class Undo extends Tools { 10 | title = 'Undo'; 11 | icon = 'undo'; 12 | name = 'Undo'; 13 | 14 | get run() { 15 | return (state, dispatch) => { 16 | undo(state, tr => dispatch(tr.setMeta('inputType', 'Undo'))); 17 | }; 18 | } 19 | 20 | get enable() { 21 | return undo; 22 | } 23 | 24 | select(state) { 25 | return undo(state); 26 | } 27 | 28 | renderTool(view) { 29 | if (isEmpty(view)) return null; 30 | return this.isDisplayed() ? ( 31 | 32 | ) : null; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/OENContainersService/OENAsideShortToolGroupService/OENAsideShortToolGroup.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { injectable, inject } from 'inversify'; 3 | import { ToolGroup, LeftMenuTitle } from 'wax-prosemirror-core'; 4 | 5 | @injectable() 6 | class OENAsideShortToolGroup extends ToolGroup { 7 | tools = []; 8 | title = (); 9 | 10 | constructor( 11 | @inject('OENAsideShortToolNote') OENAsideShortToolNote, 12 | @inject('OENAsideShortToolTip') OENAsideShortToolTip, 13 | @inject('OENAsideShortToolWarning') OENAsideShortToolWarning, 14 | @inject('OENAsideShortToolReminder') OENAsideShortToolReminder, 15 | ) { 16 | super(); 17 | this.tools = [ 18 | OENAsideShortToolNote, 19 | OENAsideShortToolTip, 20 | OENAsideShortToolWarning, 21 | OENAsideShortToolReminder, 22 | ]; 23 | } 24 | } 25 | 26 | export default OENAsideShortToolGroup; 27 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/OrderedListService/OrderedListService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import orderedListNode from './schema/orderedListNode'; 3 | import OrderedList from './OrderedList'; 4 | 5 | class OrderedListService extends Service { 6 | name = 'OrderedListService'; 7 | 8 | register() { 9 | const CreateShortCut = this.container.get('CreateShortCut'); 10 | this.container.bind('OrderedList').toDynamicValue(() => { 11 | return new OrderedList(this.config); 12 | }); 13 | const createNode = this.container.get('CreateNode'); 14 | createNode( 15 | { 16 | orderedlist: orderedListNode, 17 | }, 18 | { toWaxSchema: true }, 19 | ); 20 | CreateShortCut({ 21 | 'Shift-Ctrl-9': (state, dispatch) => { 22 | this.container.get('OrderedList').run(state, dispatch); 23 | }, 24 | }); 25 | } 26 | } 27 | 28 | export default OrderedListService; 29 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CommentsService/components/ui/trackChanges/removeNode.js: -------------------------------------------------------------------------------- 1 | import { replaceStep, ReplaceStep } from 'prosemirror-transform'; 2 | import { Slice } from 'prosemirror-model'; 3 | import { Selection } from 'prosemirror-state'; 4 | 5 | const removeNode = (tr, node, nodePos, map) => { 6 | const newNodePos = map.map(nodePos); 7 | let delStep; 8 | const selectionBefore = Selection.findFrom(tr.doc.resolve(newNodePos), -1); 9 | const start = selectionBefore.$anchor.pos; 10 | const end = newNodePos + 1; 11 | 12 | if (node.isLeaf || ['figure', 'table'].includes(node.type.name)) { 13 | delStep = new ReplaceStep( 14 | newNodePos, 15 | map.map(nodePos + node.nodeSize), 16 | Slice.empty, 17 | ); 18 | } else { 19 | delStep = replaceStep(tr.doc, start, end); 20 | } 21 | 22 | tr.step(delStep); 23 | const stepMap = delStep.getMap(); 24 | map.appendMap(stepMap); 25 | }; 26 | 27 | export default removeNode; 28 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ListsService/BulletListService/BulletListService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import bulletListNode from './schema/bulletListNode'; 3 | import BulletList from './BulletList'; 4 | 5 | class BulletListService extends Service { 6 | name = 'BulletListService'; 7 | 8 | register() { 9 | const CreateShortCut = this.container.get('CreateShortCut'); 10 | const createNode = this.container.get('CreateNode'); 11 | 12 | this.container.bind('BulletList').toDynamicValue(() => { 13 | return new BulletList(this.config); 14 | }); 15 | 16 | createNode( 17 | { 18 | bulletlist: bulletListNode, 19 | }, 20 | { toWaxSchema: true }, 21 | ); 22 | 23 | CreateShortCut({ 24 | 'Shift-Ctrl-8': (state, dispatch) => { 25 | this.container.get('BulletList').run(state, dispatch); 26 | }, 27 | }); 28 | } 29 | } 30 | 31 | export default BulletListService; 32 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultServices/LayoutService/components/componentPlugin.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/jsx-props-no-spreading */ 2 | /* eslint-disable react/no-array-index-key */ 3 | import React from 'react'; 4 | // import { useInjection } from '../../../../WaxContext'; 5 | 6 | const ComponentPlugin = renderArea => layoutProps => { 7 | // const { instance } = useInjection('Layout'); 8 | 9 | const instance = layoutProps.app.container.isBound('Layout') 10 | ? { instance: context.app.container.get('Layout') } 11 | : null; 12 | 13 | const components = instance.render(renderArea); 14 | return components 15 | ? components.map(({ component: Component, componentProps }, key) => { 16 | return ( 17 | 22 | ); 23 | }) 24 | : null; 25 | }; 26 | export default ComponentPlugin; 27 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/utilities/lib/Middleware.js: -------------------------------------------------------------------------------- 1 | export default class Middleware { 2 | constructor() { 3 | // Array prototype last 4 | if (!Array.prototype.last) { 5 | Array.prototype.last = function () { 6 | return this[this.length - 1]; 7 | }; 8 | } 9 | 10 | // Array prototype reduceOneRight 11 | if (!Array.prototype.reduceOneRight) { 12 | Array.prototype.reduceOneRight = function () { 13 | return this.slice(0, -1); 14 | }; 15 | } 16 | } 17 | 18 | use(fn) { 19 | this.go = (stack => (...args) => 20 | stack(...args.reduceOneRight(), () => { 21 | let _next = args.last(); 22 | fn.apply(this, [ 23 | ...args.reduceOneRight(), 24 | _next.bind.apply(_next, [null, ...args.reduceOneRight()]), 25 | ]); 26 | }))(this.go); 27 | } 28 | 29 | go(...args) { 30 | let _next = args.last(); 31 | _next.apply(this, args.reduceOneRight()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CommentsService/components/ui/trackChanges/TrackChangeEnable.js: -------------------------------------------------------------------------------- 1 | /* eslint react/prop-types: 0 */ 2 | import React, { useState, useMemo } from 'react'; 3 | import { MenuButton } from 'wax-prosemirror-core'; 4 | 5 | const TrackChangeEnable = ({ view = {}, item, enabled }) => { 6 | const [isEnabled, setEnabled] = useState(enabled); 7 | 8 | const handleMouseDown = e => { 9 | e.preventDefault(); 10 | setEnabled(!isEnabled); 11 | item.run(view.state, view.dispatch); 12 | }; 13 | 14 | const TrackChangeEnableComponent = useMemo( 15 | () => ( 16 | handleMouseDown(e)} 21 | title={item.title} 22 | /> 23 | ), 24 | [isEnabled], 25 | ); 26 | 27 | return TrackChangeEnableComponent; 28 | }; 29 | 30 | export default TrackChangeEnable; 31 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/schema/multipleChoiceNode.js: -------------------------------------------------------------------------------- 1 | const multipleChoiceNode = { 2 | attrs: { 3 | class: { default: 'multiple-choice-option' }, 4 | id: { default: '' }, 5 | correct: { default: false }, 6 | answer: { default: false }, 7 | feedback: { default: '' }, 8 | }, 9 | group: 'block questions', 10 | content: 'block*', 11 | // defining: true, 12 | parseDOM: [ 13 | { 14 | tag: 'div.multiple-choice-option', 15 | getAttrs(dom) { 16 | return { 17 | id: dom.getAttribute('id'), 18 | class: dom.getAttribute('class'), 19 | correct: JSON.parse(dom.getAttribute('correct').toLowerCase()), 20 | answer: JSON.parse(dom.getAttribute('answer').toLowerCase()), 21 | feedback: dom.getAttribute('feedback'), 22 | }; 23 | }, 24 | }, 25 | ], 26 | toDOM: node => ['div', node.attrs, 0], 27 | }; 28 | 29 | export default multipleChoiceNode; 30 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | const { eslint } = require('@coko/lint'); 2 | 3 | eslint.parserOptions = { 4 | ecmaVersion: 6, 5 | ecmaFeatures: { 6 | legacyDecorators: true, 7 | experimentalObjectRestSpread: true, 8 | }, 9 | }; 10 | 11 | eslint.rules['no-unused-vars'] = ['error', { varsIgnorePattern: 'inject' }]; 12 | 13 | eslint.rules['no-underscore-dangle'] = [ 14 | 'error', 15 | { allow: ['_tools', '_config'] }, 16 | ]; 17 | 18 | eslint.rules['class-methods-use-this'] = [ 19 | 1, 20 | { exceptMethods: ['run', 'enable', 'active', 'select'] }, 21 | ]; 22 | // eslint.rules['import/no-named-as-default'] = 0, 23 | 24 | eslint.rules['react/prop-types'] = [ 25 | 2, 26 | { 27 | ignore: [ 28 | 'children', 29 | 'className', 30 | 'onClick', 31 | 'onMouseDown', 32 | 'onMouseEnter', 33 | 'theme', 34 | 'node', 35 | 'view', 36 | 'getPos', 37 | 'readOnly', 38 | ], 39 | }, 40 | ]; 41 | 42 | module.exports = eslint; 43 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseQuestionService/schema/trueFalseNode.js: -------------------------------------------------------------------------------- 1 | const trueFalseNode = { 2 | attrs: { 3 | class: { default: 'true-false-option' }, 4 | id: { default: '' }, 5 | correct: { default: false }, 6 | answer: { default: false }, 7 | feedback: { default: '' }, 8 | }, 9 | group: 'block questions', 10 | content: 'block*', 11 | // defining: true, 12 | 13 | parseDOM: [ 14 | { 15 | tag: 'div.true-false-option', 16 | getAttrs(dom) { 17 | return { 18 | id: dom.getAttribute('id'), 19 | class: dom.getAttribute('class'), 20 | correct: JSON.parse(dom.getAttribute('correct').toLowerCase()), 21 | answer: JSON.parse(dom.getAttribute('answer').toLowerCase()), 22 | feedback: dom.getAttribute('feedback'), 23 | }; 24 | }, 25 | }, 26 | ], 27 | toDOM: node => ['div', node.attrs, 0], 28 | }; 29 | 30 | export default trueFalseNode; 31 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/defaultServices/OverlayService/OverlayComponent.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/jsx-props-no-spreading */ 2 | import React, { useMemo, useContext } from 'react'; 3 | import Overlay from './OverLay'; 4 | import { WaxContext } from '../../../WaxContext'; 5 | import usePosition from './usePosition'; 6 | 7 | export default (Component, markType) => props => { 8 | const context = useContext(WaxContext); 9 | const [position, setPosition, mark] = usePosition(markType); 10 | 11 | const component = useMemo( 12 | () => ( 13 | 19 | ), 20 | [JSON.stringify(mark), position, context.activeViewId], 21 | ); 22 | const visible = position.left !== null; 23 | return ( 24 | 25 | {props.activeViewId === context.activeViewId && visible && component} 26 | 27 | ); 28 | }; 29 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/ExternalAPIContentService/ExternalAPIContentService.js: -------------------------------------------------------------------------------- 1 | import { Service } from 'wax-prosemirror-core'; 2 | import ExternalAPIContentTool from './ExternalAPIContentTool'; 3 | import ExternalAPIContentToolGroupService from './ExternalAPIContentToolGroupService/ExternalAPIContentToolGroupService'; 4 | import ExternalAPIContentPlaceHolderPlugin from './plugins/ExternalAPIContentPlaceHolderPlugin'; 5 | import './externalApiContent.css'; 6 | 7 | class ExternalAPIContentService extends Service { 8 | name = 'ExternalAPIContentService'; 9 | 10 | boot() { 11 | this.app.PmPlugins.add( 12 | 'ExternalAPIContentPlaceHolder', 13 | ExternalAPIContentPlaceHolderPlugin('ExternalAPIContentPlaceHolder'), 14 | ); 15 | } 16 | 17 | register() { 18 | this.container.bind('ExternalAPIContentTool').to(ExternalAPIContentTool); 19 | } 20 | 21 | dependencies = [new ExternalAPIContentToolGroupService()]; 22 | } 23 | 24 | export default ExternalAPIContentService; 25 | -------------------------------------------------------------------------------- /wax-questions-service/src/FillTheGapQuestionService/FillTheGapNodeView.js: -------------------------------------------------------------------------------- 1 | import { QuestionsNodeView } from 'wax-prosemirror-core'; 2 | 3 | export default class FillTheGapNodeView extends QuestionsNodeView { 4 | constructor( 5 | node, 6 | view, 7 | getPos, 8 | decorations, 9 | createPortal, 10 | Component, 11 | context, 12 | ) { 13 | super(node, view, getPos, decorations, createPortal, Component, context); 14 | 15 | this.node = node; 16 | this.outerView = view; 17 | this.getPos = getPos; 18 | this.context = context; 19 | } 20 | 21 | static name() { 22 | return 'fill_the_gap'; 23 | } 24 | 25 | selectNode() { 26 | this.context.pmViews[this.node.attrs.id].focus(); 27 | } 28 | 29 | stopEvent(event) { 30 | return ( 31 | this.context.pmViews[this.node.attrs.id] !== undefined && 32 | event.target !== undefined && 33 | this.context.pmViews[this.node.attrs.id].dom.contains(event.target) 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/EditingSuggestingService/EditingSuggesting.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { injectable } from 'inversify'; 3 | import { isEmpty } from 'lodash'; 4 | import { v4 as uuidv4 } from 'uuid'; 5 | import { Tools } from 'wax-prosemirror-core'; 6 | import EditingSuggestingDropDown from './components/EditingSuggestingDropDown'; 7 | 8 | @injectable() 9 | export default class EditingSuggesting extends Tools { 10 | title = ''; 11 | label = ''; 12 | name = 'EditingSuggesting'; 13 | 14 | get run() { 15 | return () => { 16 | return true; 17 | }; 18 | } 19 | 20 | get enable() { 21 | return () => { 22 | return true; 23 | }; 24 | } 25 | 26 | renderTool(view) { 27 | if (isEmpty(view)) return null; 28 | return this.isDisplayed() ? ( 29 | 35 | ) : null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /wax-questions-service/src/EssayService/components/EssayPromptComponent.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import styled from 'styled-components'; 3 | import { WaxContext } from 'wax-prosemirror-core'; 4 | import EditorComponent from '../../MultipleChoiceQuestionService/components/EditorComponent'; 5 | 6 | const EditorWrapper = styled.div` 7 | display: ${props => (props.testMode ? 'none' : 'block')}; 8 | `; 9 | 10 | export default ({ node, view, getPos }) => { 11 | const context = useContext(WaxContext); 12 | const { 13 | pmViews: { main }, 14 | } = context; 15 | const customProps = main.props.customValues; 16 | 17 | const { testMode } = customProps; 18 | 19 | return ( 20 | 21 | 28 | 29 | ); 30 | }; 31 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/CustomTagInlineService/schema/customtagInlineMark.js: -------------------------------------------------------------------------------- 1 | const customtagInlineMark = { 2 | attrs: { 3 | class: { default: null }, 4 | tags: [], 5 | type: { default: 'inline' }, 6 | }, 7 | inclusive: false, 8 | parseDOM: [ 9 | { 10 | tag: 'span[data-type="inline"]', 11 | getAttrs(hook, next) { 12 | Object.assign(hook, { 13 | class: hook.dom.getAttribute('class'), 14 | tags: JSON.parse(hook.dom.dataset.tags), 15 | type: hook.dom.dataset.type, 16 | }); 17 | next(); 18 | }, 19 | }, 20 | ], 21 | toDOM(hook, next) { 22 | // eslint-disable-next-line no-param-reassign 23 | hook.value = [ 24 | 'span', 25 | { 26 | class: hook.node.attrs.class, 27 | 'data-type': hook.node.attrs.type, 28 | 'data-tags': JSON.stringify(hook.node.attrs.tags), 29 | }, 30 | ]; 31 | next(); 32 | }, 33 | }; 34 | 35 | export default customtagInlineMark; 36 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/CustomTagService/index.js: -------------------------------------------------------------------------------- 1 | import CustomTagBlockService from './CustomTagBlockService/CustomTagBlockService'; 2 | import CustomTagBlockNewService from './CustomTagBlockNewService/CustomTagBlockNewService'; 3 | import CustomTagInlineService from './CustomTagInlineService/CustomTagInlineService'; 4 | import CustomTagBlockToolGroupService from './CustomTagToolGroupService/CustomTagBlockToolGroupService/CustomTagBlockToolGroupService'; 5 | import CustomTagInlineToolGroupService from './CustomTagToolGroupService/CustomTagInlineToolGroupService/CustomTagInlineToolGroupService'; 6 | import CustomTagBlockNewToolGroupService from './CustomTagToolGroupService/CustomTagBlockNewToolGroupService/CustomTagBlockNewToolGroupService'; 7 | 8 | export default [ 9 | new CustomTagBlockNewService(), 10 | new CustomTagBlockService(), 11 | new CustomTagInlineService(), 12 | new CustomTagBlockToolGroupService(), 13 | new CustomTagInlineToolGroupService(), 14 | new CustomTagBlockNewToolGroupService(), 15 | ]; 16 | -------------------------------------------------------------------------------- /wax-prosemirror-services/src/InlineAnnotations/index.js: -------------------------------------------------------------------------------- 1 | import CodeService from './CodeService/CodeService'; 2 | import StrongService from './StrongService/StrongService'; 3 | import EmphasisService from './EmphasisService/EmphasisService'; 4 | import SubscriptService from './SubscriptService/SubscriptService'; 5 | import SuperscriptService from './SuperscriptService/SuperscriptService'; 6 | import StrikeThroughService from './StrikeThroughService/StrikeThroughService'; 7 | import UnderlineService from './UnderlineService/UnderlineService'; 8 | import SmallCapsService from './SmallCapsService/SmallCapsService'; 9 | import AnnotationToolGroupService from './AnnotationToolGroupService/AnnotationToolGroupService'; 10 | 11 | export default [ 12 | new CodeService(), 13 | new StrongService(), 14 | new EmphasisService(), 15 | new SubscriptService(), 16 | new SuperscriptService(), 17 | new StrikeThroughService(), 18 | new UnderlineService(), 19 | new SmallCapsService(), 20 | new AnnotationToolGroupService(), 21 | ]; 22 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/components/LeftMenuTitle.js: -------------------------------------------------------------------------------- 1 | /* eslint react/prop-types: 0 */ 2 | 3 | import React from 'react'; 4 | import { isEmpty } from 'lodash'; 5 | import { useTranslation } from 'react-i18next'; 6 | import styled from 'styled-components'; 7 | 8 | const LeftMenuStyled = styled.div` 9 | border-bottom: 1px solid #d9d9d9; 10 | color: #979797; 11 | font-family: 'Fira Sans'; 12 | font-size: 15px; 13 | font-weight: bold; 14 | letter-spacing: 0.6px; 15 | list-style: none; 16 | line-height: 0; 17 | margin: 5px 0; 18 | display: block; 19 | padding: 20px 0 10px; 20 | margin-left: 10px; 21 | text-align: left; 22 | text-transform: uppercase; 23 | width: 51%; 24 | `; 25 | 26 | const LeftMenuTitle = ({ title }) => { 27 | const { t, i18n } = useTranslation(); 28 | return ( 29 | 30 | {!isEmpty(i18n) && i18n.exists(`Wax.Various.${title}`) 31 | ? t(`Wax.Various.${title}`) 32 | : title} 33 | 34 | ); 35 | }; 36 | 37 | export default LeftMenuTitle; 38 | -------------------------------------------------------------------------------- /wax-questions-service/src/MultipleDropDownService/MultipleDropDownContainerNodeView.js: -------------------------------------------------------------------------------- 1 | import { QuestionsNodeView } from 'wax-prosemirror-core'; 2 | 3 | export default class MultipleDropDownContainerNodeView extends QuestionsNodeView { 4 | constructor( 5 | node, 6 | view, 7 | getPos, 8 | decorations, 9 | createPortal, 10 | Component, 11 | context, 12 | ) { 13 | super(node, view, getPos, decorations, createPortal, Component, context); 14 | 15 | this.node = node; 16 | this.outerView = view; 17 | this.getPos = getPos; 18 | this.context = context; 19 | } 20 | 21 | static name() { 22 | return 'multiple_drop_down_container'; 23 | } 24 | 25 | stopEvent(event) { 26 | if ( 27 | event.target.type === 'textarea' || 28 | event.target.type === 'text' || 29 | !event.target.type 30 | ) { 31 | return true; 32 | } 33 | const innerView = this.context.pmViews[this.node.attrs.id]; 34 | return innerView && innerView.dom.contains(event.target); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /wax-prosemirror-core/src/config/plugins/placeholder.js: -------------------------------------------------------------------------------- 1 | import { Plugin, PluginKey } from 'prosemirror-state'; 2 | import { Decoration, DecorationSet } from 'prosemirror-view'; 3 | 4 | const placeHolderText = new PluginKey('placeHolderText'); 5 | 6 | export default props => { 7 | return new Plugin({ 8 | key: placeHolderText, 9 | props: { 10 | decorations: state => { 11 | const decorations = []; 12 | const decorate = (node, pos) => { 13 | if ( 14 | node.type.isBlock && 15 | node.childCount === 0 && 16 | state.doc.content.childCount === 1 17 | ) { 18 | decorations.push( 19 | Decoration.node(pos, pos + node.nodeSize, { 20 | class: 'empty-node', 21 | 'data-content': props.content, 22 | }), 23 | ); 24 | } 25 | }; 26 | state.doc.descendants(decorate); 27 | 28 | return DecorationSet.create(state.doc, decorations); 29 | }, 30 | }, 31 | }); 32 | }; 33 | --------------------------------------------------------------------------------