From f2e6d3d8ef1658959f97c3267625d5cd7e91c758 Mon Sep 17 00:00:00 2001 From: Sven Adlung Date: Tue, 16 Nov 2021 15:42:40 +0100 Subject: [PATCH] Add TaskList and TaskItem demo for React --- demos/src/Nodes/TaskItem/React/index.html | 15 +++ demos/src/Nodes/TaskItem/React/index.jsx | 63 +++++++++++ demos/src/Nodes/TaskItem/React/index.spec.js | 7 ++ demos/src/Nodes/TaskItem/React/styles.scss | 22 ++++ demos/src/Nodes/TaskList/React/index.html | 15 +++ demos/src/Nodes/TaskList/React/index.jsx | 63 +++++++++++ demos/src/Nodes/TaskList/React/index.spec.js | 113 +++++++++++++++++++ demos/src/Nodes/TaskList/React/styles.scss | 22 ++++ 8 files changed, 320 insertions(+) create mode 100644 demos/src/Nodes/TaskItem/React/index.html create mode 100644 demos/src/Nodes/TaskItem/React/index.jsx create mode 100644 demos/src/Nodes/TaskItem/React/index.spec.js create mode 100644 demos/src/Nodes/TaskItem/React/styles.scss create mode 100644 demos/src/Nodes/TaskList/React/index.html create mode 100644 demos/src/Nodes/TaskList/React/index.jsx create mode 100644 demos/src/Nodes/TaskList/React/index.spec.js create mode 100644 demos/src/Nodes/TaskList/React/styles.scss diff --git a/demos/src/Nodes/TaskItem/React/index.html b/demos/src/Nodes/TaskItem/React/index.html new file mode 100644 index 00000000..fe80515c --- /dev/null +++ b/demos/src/Nodes/TaskItem/React/index.html @@ -0,0 +1,15 @@ + + + + + + + +
+ + + diff --git a/demos/src/Nodes/TaskItem/React/index.jsx b/demos/src/Nodes/TaskItem/React/index.jsx new file mode 100644 index 00000000..a1443e36 --- /dev/null +++ b/demos/src/Nodes/TaskItem/React/index.jsx @@ -0,0 +1,63 @@ +import React from 'react' +import { useEditor, EditorContent } from '@tiptap/react' +import Document from '@tiptap/extension-document' +import Paragraph from '@tiptap/extension-paragraph' +import Text from '@tiptap/extension-text' +import TaskList from '@tiptap/extension-task-list' +import TaskItem from '@tiptap/extension-task-item' +import './styles.scss' + +export default () => { + const editor = useEditor({ + extensions: [ + Document, + Paragraph, + Text, + TaskList, + TaskItem.configure({ + nested: true, + }), + ], + content: ` + + `, + }) + + if (!editor) { + return null + } + + return ( + <> + + + + + + + + ) +} diff --git a/demos/src/Nodes/TaskItem/React/index.spec.js b/demos/src/Nodes/TaskItem/React/index.spec.js new file mode 100644 index 00000000..a8da084e --- /dev/null +++ b/demos/src/Nodes/TaskItem/React/index.spec.js @@ -0,0 +1,7 @@ +context('/src/Nodes/TaskItem/React/', () => { + before(() => { + cy.visit('/src/Nodes/TaskItem/React/') + }) + + // TODO: Write tests +}) diff --git a/demos/src/Nodes/TaskItem/React/styles.scss b/demos/src/Nodes/TaskItem/React/styles.scss new file mode 100644 index 00000000..2a3190c0 --- /dev/null +++ b/demos/src/Nodes/TaskItem/React/styles.scss @@ -0,0 +1,22 @@ +ul[data-type="taskList"] { + list-style: none; + padding: 0; + + p { + margin: 0; + } + + li { + display: flex; + + > label { + flex: 0 0 auto; + margin-right: 0.5rem; + user-select: none; + } + + > div { + flex: 1 1 auto; + } + } +} diff --git a/demos/src/Nodes/TaskList/React/index.html b/demos/src/Nodes/TaskList/React/index.html new file mode 100644 index 00000000..10a1ad79 --- /dev/null +++ b/demos/src/Nodes/TaskList/React/index.html @@ -0,0 +1,15 @@ + + + + + + + +
+ + + diff --git a/demos/src/Nodes/TaskList/React/index.jsx b/demos/src/Nodes/TaskList/React/index.jsx new file mode 100644 index 00000000..a1443e36 --- /dev/null +++ b/demos/src/Nodes/TaskList/React/index.jsx @@ -0,0 +1,63 @@ +import React from 'react' +import { useEditor, EditorContent } from '@tiptap/react' +import Document from '@tiptap/extension-document' +import Paragraph from '@tiptap/extension-paragraph' +import Text from '@tiptap/extension-text' +import TaskList from '@tiptap/extension-task-list' +import TaskItem from '@tiptap/extension-task-item' +import './styles.scss' + +export default () => { + const editor = useEditor({ + extensions: [ + Document, + Paragraph, + Text, + TaskList, + TaskItem.configure({ + nested: true, + }), + ], + content: ` + + `, + }) + + if (!editor) { + return null + } + + return ( + <> + + + + + + + + ) +} diff --git a/demos/src/Nodes/TaskList/React/index.spec.js b/demos/src/Nodes/TaskList/React/index.spec.js new file mode 100644 index 00000000..f9dab673 --- /dev/null +++ b/demos/src/Nodes/TaskList/React/index.spec.js @@ -0,0 +1,113 @@ +context('/src/Nodes/TaskList/React/', () => { + before(() => { + cy.visit('/src/Nodes/TaskList/React/') + }) + + beforeEach(() => { + cy.get('.ProseMirror').then(([{ editor }]) => { + editor.commands.setContent('

Example Text

') + cy.get('.ProseMirror').type('{selectall}') + }) + }) + + it('should parse unordered lists correctly', () => { + cy.get('.ProseMirror').then(([{ editor }]) => { + editor.commands.setContent( + '
  • Example Text

', + ) + expect(editor.getHTML()).to.eq( + '
  • Example Text

', + ) + }) + }) + + it('should parse unordered lists without paragraphs correctly', () => { + cy.get('.ProseMirror').then(([{ editor }]) => { + editor.commands.setContent( + '
  • Example Text
', + ) + expect(editor.getHTML()).to.eq( + '
  • Example Text

', + ) + }) + }) + + it('the button should make the selected line a task list item', () => { + cy.get('.ProseMirror ul').should('not.exist') + + cy.get('.ProseMirror ul li').should('not.exist') + + cy.get('button:nth-child(1)').click() + + cy.get('.ProseMirror').find('ul[data-type="taskList"]').should('contain', 'Example Text') + + cy.get('.ProseMirror').find('ul[data-type="taskList"] li').should('contain', 'Example Text') + }) + + it('the button should toggle the task list', () => { + cy.get('.ProseMirror ul').should('not.exist') + + cy.get('button:nth-child(1)').click() + + cy.get('.ProseMirror').find('ul[data-type="taskList"]').should('contain', 'Example Text') + + cy.get('button:nth-child(1)').click() + + cy.get('.ProseMirror ul').should('not.exist') + }) + + it('should make the paragraph a task list when the keyboard shortcut is pressed', () => { + cy.get('.ProseMirror') + .trigger('keydown', { modKey: true, shiftKey: true, key: '9' }) + .find('ul li') + .should('contain', 'Example Text') + }) + + it('should leave the list with double enter', () => { + cy.get('.ProseMirror').then(([{ editor }]) => { + editor.commands.clearContent() + }) + + cy.get('.ProseMirror').type('[ ] List Item 1{enter}{enter}Paragraph') + + cy.get('.ProseMirror').find('li').its('length').should('eq', 1) + + cy.get('.ProseMirror').find('p').should('contain', 'Paragraph') + }) + + it('should make a task list from square brackets', () => { + cy.get('.ProseMirror').then(([{ editor }]) => { + editor.commands.clearContent() + }) + + cy.get('.ProseMirror').type('[ ] List Item 1{enter}List Item 2') + + cy.get('.ProseMirror') + .find('li:nth-child(1)') + .should('contain', 'List Item 1') + .should('have.attr', 'data-checked', 'false') + + cy.get('.ProseMirror') + .find('li:nth-child(2)') + .should('contain', 'List Item 2') + .should('have.attr', 'data-checked', 'false') + }) + + it('should make a task list from checked square brackets', () => { + cy.get('.ProseMirror').then(([{ editor }]) => { + editor.commands.clearContent() + }) + + cy.get('.ProseMirror').type('[x] List Item 1{enter}List Item 2') + + cy.get('.ProseMirror') + .find('li:nth-child(1)') + .should('contain', 'List Item 1') + .should('have.attr', 'data-checked', 'true') + + cy.get('.ProseMirror') + .find('li:nth-child(2)') + .should('contain', 'List Item 2') + .should('have.attr', 'data-checked', 'false') + }) +}) diff --git a/demos/src/Nodes/TaskList/React/styles.scss b/demos/src/Nodes/TaskList/React/styles.scss new file mode 100644 index 00000000..2a3190c0 --- /dev/null +++ b/demos/src/Nodes/TaskList/React/styles.scss @@ -0,0 +1,22 @@ +ul[data-type="taskList"] { + list-style: none; + padding: 0; + + p { + margin: 0; + } + + li { + display: flex; + + > label { + flex: 0 0 auto; + margin-right: 0.5rem; + user-select: none; + } + + > div { + flex: 1 1 auto; + } + } +}