diff --git a/demos/src/Nodes/Blockquote/Vue/index.html b/demos/src/Nodes/Blockquote/Vue/index.html
new file mode 100644
index 00000000..f3549c58
--- /dev/null
+++ b/demos/src/Nodes/Blockquote/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Blockquote/Vue/index.spec.js b/demos/src/Nodes/Blockquote/Vue/index.spec.js
new file mode 100644
index 00000000..30fa8c45
--- /dev/null
+++ b/demos/src/Nodes/Blockquote/Vue/index.spec.js
@@ -0,0 +1,104 @@
+context('/demos/Nodes/Blockquote', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/Blockquote')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ cy.get('.ProseMirror').type('{selectall}')
+ })
+ })
+
+ it('should parse blockquote tags correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ expect(editor.getHTML()).to.eq('Example Text
')
+ })
+ })
+
+ it('should parse blockquote tags 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 blockquote', () => {
+ cy.get('.ProseMirror blockquote')
+ .should('not.exist')
+
+ cy.get('button:first')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('blockquote')
+ .should('contain', 'Example Text')
+ })
+
+ it('the button should wrap all nodes in one blockquote', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
Example Text
')
+ cy.get('.ProseMirror').type('{selectall}')
+ })
+
+ cy.get('button:first')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('blockquote')
+ .should('have.length', 1)
+ })
+
+ it('the button should toggle the blockquote', () => {
+ cy.get('.ProseMirror blockquote')
+ .should('not.exist')
+
+ cy.get('button:first')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('blockquote')
+ .should('contain', 'Example Text')
+
+ cy.get('.ProseMirror')
+ .type('{selectall}')
+
+ cy.get('button:first')
+ .click()
+
+ cy.get('.ProseMirror blockquote')
+ .should('not.exist')
+ })
+
+ it('should make the selected line a blockquote when the keyboard shortcut is pressed', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { shiftKey: true, modKey: true, key: 'b' })
+ .find('blockquote')
+ .should('contain', 'Example Text')
+ })
+
+ it('should toggle the blockquote when the keyboard shortcut is pressed', () => {
+ cy.get('.ProseMirror blockquote')
+ .should('not.exist')
+
+ cy.get('.ProseMirror')
+ .trigger('keydown', { shiftKey: true, modKey: true, key: 'b' })
+ .find('blockquote')
+ .should('contain', 'Example Text')
+
+ cy.get('.ProseMirror')
+ .type('{selectall}')
+ .trigger('keydown', { shiftKey: true, modKey: true, key: 'b' })
+
+ cy.get('.ProseMirror blockquote')
+ .should('not.exist')
+ })
+
+ it('should make a blockquote from markdown shortcuts', () => {
+ cy.get('.ProseMirror')
+ .type('> Quote')
+ .find('blockquote')
+ .should('contain', 'Quote')
+ })
+})
diff --git a/demos/src/Nodes/Blockquote/Vue/index.vue b/demos/src/Nodes/Blockquote/Vue/index.vue
new file mode 100644
index 00000000..3c51e0d9
--- /dev/null
+++ b/demos/src/Nodes/Blockquote/Vue/index.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/BulletList/Vue/index.html b/demos/src/Nodes/BulletList/Vue/index.html
new file mode 100644
index 00000000..baaee646
--- /dev/null
+++ b/demos/src/Nodes/BulletList/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/BulletList/Vue/index.spec.js b/demos/src/Nodes/BulletList/Vue/index.spec.js
new file mode 100644
index 00000000..7fc6d344
--- /dev/null
+++ b/demos/src/Nodes/BulletList/Vue/index.spec.js
@@ -0,0 +1,152 @@
+context('/demos/Nodes/BulletList', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/BulletList')
+ })
+
+ 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('')
+ expect(editor.getHTML()).to.eq('')
+ })
+ })
+
+ it('should parse unordered lists without paragraphs correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('')
+ expect(editor.getHTML()).to.eq('')
+ })
+ })
+
+ it('the button should make the selected line a bullet 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')
+ .should('contain', 'Example Text')
+
+ cy.get('.ProseMirror')
+ .find('ul li')
+ .should('contain', 'Example Text')
+ })
+
+ it('the button should toggle the bullet list', () => {
+ cy.get('.ProseMirror ul')
+ .should('not.exist')
+
+ cy.get('button:nth-child(1)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('ul')
+ .should('contain', 'Example Text')
+
+ cy.get('button:nth-child(1)')
+ .click()
+
+ cy.get('.ProseMirror ul')
+ .should('not.exist')
+ })
+
+ 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 the paragraph a bullet list keyboard shortcut is pressed', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, shiftKey: true, key: '8' })
+ .find('ul li')
+ .should('contain', 'Example Text')
+ })
+
+ it('should make a bullet list from an asterisk', () => {
+ 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')
+
+ cy.get('.ProseMirror')
+ .find('li:nth-child(2)')
+ .should('contain', 'List Item 2')
+ })
+
+ it('should make a bullet list from a dash', () => {
+ 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')
+
+ cy.get('.ProseMirror')
+ .find('li:nth-child(2)')
+ .should('contain', 'List Item 2')
+ })
+
+ it('should make a bullet list from a plus', () => {
+ 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')
+
+ cy.get('.ProseMirror')
+ .find('li:nth-child(2)')
+ .should('contain', 'List Item 2')
+ })
+
+ it('should remove the bullet list after pressing backspace', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+ })
+
+ cy.get('.ProseMirror')
+ .type('* {backspace}Example')
+
+ cy.get('.ProseMirror')
+ .find('p')
+ .should('contain', '* Example')
+ })
+})
diff --git a/demos/src/Nodes/BulletList/Vue/index.vue b/demos/src/Nodes/BulletList/Vue/index.vue
new file mode 100644
index 00000000..12dabda9
--- /dev/null
+++ b/demos/src/Nodes/BulletList/Vue/index.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/CodeBlock/Vue/index.html b/demos/src/Nodes/CodeBlock/Vue/index.html
new file mode 100644
index 00000000..8066130c
--- /dev/null
+++ b/demos/src/Nodes/CodeBlock/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/CodeBlock/Vue/index.spec.js b/demos/src/Nodes/CodeBlock/Vue/index.spec.js
new file mode 100644
index 00000000..abb0f085
--- /dev/null
+++ b/demos/src/Nodes/CodeBlock/Vue/index.spec.js
@@ -0,0 +1,185 @@
+context('/demos/Nodes/CodeBlock', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/CodeBlock')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ cy.get('.ProseMirror').type('{selectall}')
+ })
+ })
+
+ it('should parse code blocks correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ expect(editor.getHTML()).to.eq('Example Text
')
+ })
+ })
+
+ it('should parse code blocks with language 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 code block', () => {
+ cy.get('button:first')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('pre')
+ .should('contain', 'Example Text')
+ })
+
+ it('the button should toggle the code block', () => {
+ cy.get('button:first')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('pre')
+ .should('contain', 'Example Text')
+
+ cy.get('.ProseMirror')
+ .type('{selectall}')
+
+ cy.get('button:first')
+ .click()
+
+ cy.get('.ProseMirror pre')
+ .should('not.exist')
+ })
+
+ it('the keyboard shortcut should make the selected line a code block', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, altKey: true, key: 'c' })
+ .find('pre')
+ .should('contain', 'Example Text')
+ })
+
+ it('the keyboard shortcut should toggle the code block', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, altKey: true, key: 'c' })
+ .find('pre')
+ .should('contain', 'Example Text')
+
+ cy.get('.ProseMirror')
+ .type('{selectall}')
+ .trigger('keydown', { modKey: true, altKey: true, key: 'c' })
+
+ cy.get('.ProseMirror pre')
+ .should('not.exist')
+ })
+
+ it('should parse the language from a HTML code block', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('body { display: none; }
')
+
+ cy.get('.ProseMirror')
+ .find('pre>code.language-css')
+ .should('have.length', 1)
+ })
+ })
+
+ it('should make a code block from backtick markdown shortcuts', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+
+ cy.get('.ProseMirror')
+ .type('``` Code')
+ .find('pre>code')
+ .should('contain', 'Code')
+ })
+ })
+
+ it('should make a code block from tilde markdown shortcuts', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+
+ cy.get('.ProseMirror')
+ .type('~~~ Code')
+ .find('pre>code')
+ .should('contain', 'Code')
+ })
+ })
+
+ it('should make a code block for js with backticks', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+
+ cy.get('.ProseMirror')
+ .type('```js Code')
+ .find('pre>code.language-js')
+ .should('contain', 'Code')
+ })
+ })
+
+ it('should make a code block for js with tildes', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+
+ cy.get('.ProseMirror')
+ .type('~~~js Code')
+ .find('pre>code.language-js')
+ .should('contain', 'Code')
+ })
+ })
+
+ it('reverts the markdown shortcut when pressing backspace', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+
+ cy.get('.ProseMirror')
+ .type('``` {backspace}')
+
+ cy.get('.ProseMirror pre')
+ .should('not.exist')
+ })
+ })
+
+ it('removes the code block when pressing backspace', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+
+ cy.get('.ProseMirror pre')
+ .should('not.exist')
+
+ cy.get('.ProseMirror')
+ .type('Paragraph{enter}``` A{backspace}{backspace}')
+
+ cy.get('.ProseMirror pre')
+ .should('not.exist')
+ })
+ })
+
+ it('removes the code block when pressing backspace, even with blank lines', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+
+ cy.get('.ProseMirror pre')
+ .should('not.exist')
+
+ cy.get('.ProseMirror')
+ .type('Paragraph{enter}{enter}``` A{backspace}{backspace}')
+
+ cy.get('.ProseMirror pre')
+ .should('not.exist')
+ })
+ })
+
+ it('removes the code block when pressing backspace, even at start of document', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+
+ cy.get('.ProseMirror pre')
+ .should('not.exist')
+
+ cy.get('.ProseMirror')
+ .type('``` A{leftArrow}{backspace}')
+
+ cy.get('.ProseMirror pre')
+ .should('not.exist')
+ })
+ })
+})
diff --git a/demos/src/Nodes/CodeBlock/Vue/index.vue b/demos/src/Nodes/CodeBlock/Vue/index.vue
new file mode 100644
index 00000000..0ba8dcbb
--- /dev/null
+++ b/demos/src/Nodes/CodeBlock/Vue/index.vue
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/CodeBlockLowlight/Vue/index.html b/demos/src/Nodes/CodeBlockLowlight/Vue/index.html
new file mode 100644
index 00000000..d2435ccb
--- /dev/null
+++ b/demos/src/Nodes/CodeBlockLowlight/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/CodeBlockLowlight/Vue/index.vue b/demos/src/Nodes/CodeBlockLowlight/Vue/index.vue
new file mode 100644
index 00000000..4297b133
--- /dev/null
+++ b/demos/src/Nodes/CodeBlockLowlight/Vue/index.vue
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Document/Vue/index.html b/demos/src/Nodes/Document/Vue/index.html
new file mode 100644
index 00000000..001ae3cb
--- /dev/null
+++ b/demos/src/Nodes/Document/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Document/Vue/index.spec.js b/demos/src/Nodes/Document/Vue/index.spec.js
new file mode 100644
index 00000000..6f7a5abe
--- /dev/null
+++ b/demos/src/Nodes/Document/Vue/index.spec.js
@@ -0,0 +1,26 @@
+context('/demos/Nodes/Document', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/Document')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('')
+ })
+ })
+
+ it('should return the document in as json', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ const json = editor.getJSON()
+
+ expect(json).to.deep.equal({
+ type: 'doc',
+ content: [
+ {
+ type: 'paragraph',
+ },
+ ],
+ })
+ })
+ })
+})
diff --git a/demos/src/Nodes/Document/Vue/index.vue b/demos/src/Nodes/Document/Vue/index.vue
new file mode 100644
index 00000000..5862e7a4
--- /dev/null
+++ b/demos/src/Nodes/Document/Vue/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/HardBreak/Vue/index.html b/demos/src/Nodes/HardBreak/Vue/index.html
new file mode 100644
index 00000000..2ba2eab7
--- /dev/null
+++ b/demos/src/Nodes/HardBreak/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/HardBreak/Vue/index.spec.js b/demos/src/Nodes/HardBreak/Vue/index.spec.js
new file mode 100644
index 00000000..8c0097d1
--- /dev/null
+++ b/demos/src/Nodes/HardBreak/Vue/index.spec.js
@@ -0,0 +1,58 @@
+context('/demos/Nodes/HardBreak', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/HardBreak')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ })
+ })
+
+ it('should parse hard breaks correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example
Text
')
+ expect(editor.getHTML()).to.eq('Example
Text
')
+ })
+ })
+
+ it('should parse hard breaks with self-closing tag correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example
Text
')
+ expect(editor.getHTML()).to.eq('Example
Text
')
+ })
+ })
+
+ it('the button should add a line break', () => {
+ cy.get('.ProseMirror br')
+ .should('not.exist')
+
+ cy.get('button:first')
+ .click()
+
+ cy.get('.ProseMirror br')
+ .should('exist')
+ })
+
+ it('the default keyboard shortcut should add a line break', () => {
+ cy.get('.ProseMirror br')
+ .should('not.exist')
+
+ cy.get('.ProseMirror')
+ .trigger('keydown', { shiftKey: true, key: 'Enter' })
+
+ cy.get('.ProseMirror br')
+ .should('exist')
+ })
+
+ it('the alternative keyboard shortcut should add a line break', () => {
+ cy.get('.ProseMirror br')
+ .should('not.exist')
+
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, key: 'Enter' })
+
+ cy.get('.ProseMirror br')
+ .should('exist')
+ })
+})
diff --git a/demos/src/Nodes/HardBreak/Vue/index.vue b/demos/src/Nodes/HardBreak/Vue/index.vue
new file mode 100644
index 00000000..c0a7cef4
--- /dev/null
+++ b/demos/src/Nodes/HardBreak/Vue/index.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Heading/Vue/index.html b/demos/src/Nodes/Heading/Vue/index.html
new file mode 100644
index 00000000..94e972ae
--- /dev/null
+++ b/demos/src/Nodes/Heading/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Heading/Vue/index.spec.js b/demos/src/Nodes/Heading/Vue/index.spec.js
new file mode 100644
index 00000000..8a9179bc
--- /dev/null
+++ b/demos/src/Nodes/Heading/Vue/index.spec.js
@@ -0,0 +1,142 @@
+context('/demos/Nodes/Heading', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/Heading')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ cy.get('.ProseMirror').type('{selectall}')
+ })
+ })
+
+ const headings = [
+ 'Example Text
',
+ 'Example Text
',
+ 'Example Text
',
+ ]
+
+ headings.forEach(html => {
+ it(`should parse headings correctly (${html})`, () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent(html)
+ expect(editor.getHTML()).to.eq(html)
+ })
+ })
+ })
+
+ it('should omit disabled heading levels', () => {
+ 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 h1', () => {
+ cy.get('.ProseMirror h1')
+ .should('not.exist')
+
+ cy.get('button:nth-child(1)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('h1')
+ .should('contain', 'Example Text')
+ })
+
+ it('the button should make the selected line a h2', () => {
+ cy.get('.ProseMirror h2')
+ .should('not.exist')
+
+ cy.get('button:nth-child(2)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('h2')
+ .should('contain', 'Example Text')
+ })
+
+ it('the button should make the selected line a h3', () => {
+ cy.get('.ProseMirror h3')
+ .should('not.exist')
+
+ cy.get('button:nth-child(3)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('h3')
+ .should('contain', 'Example Text')
+ })
+
+ it('the button should toggle the heading', () => {
+ cy.get('.ProseMirror h1')
+ .should('not.exist')
+
+ cy.get('button:nth-child(1)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('h1')
+ .should('contain', 'Example Text')
+
+ cy.get('button:nth-child(1)')
+ .click()
+
+ cy.get('.ProseMirror h1')
+ .should('not.exist')
+ })
+
+ it('should make the paragraph a h1 keyboard shortcut is pressed', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, altKey: true, key: '1' })
+ .find('h1')
+ .should('contain', 'Example Text')
+ })
+
+ it('should make the paragraph a h2 keyboard shortcut is pressed', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, altKey: true, key: '2' })
+ .find('h2')
+ .should('contain', 'Example Text')
+ })
+
+ it('should make the paragraph a h3 keyboard shortcut is pressed', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, altKey: true, key: '3' })
+ .find('h3')
+ .should('contain', 'Example Text')
+ })
+
+ it('should make a h1 from the default markdown shortcut', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+ })
+
+ cy.get('.ProseMirror')
+ .type('# Headline')
+ .find('h1')
+ .should('contain', 'Headline')
+ })
+
+ it('should make a h2 from the default markdown shortcut', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+ })
+
+ cy.get('.ProseMirror')
+ .type('## Headline')
+ .find('h2')
+ .should('contain', 'Headline')
+ })
+
+ it('should make a h3 from the default markdown shortcut', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+ })
+
+ cy.get('.ProseMirror')
+ .type('### Headline')
+ .find('h3')
+ .should('contain', 'Headline')
+ })
+})
diff --git a/demos/src/Nodes/Heading/Vue/index.vue b/demos/src/Nodes/Heading/Vue/index.vue
new file mode 100644
index 00000000..69d1cd56
--- /dev/null
+++ b/demos/src/Nodes/Heading/Vue/index.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/HorizontalRule/Vue/index.html b/demos/src/Nodes/HorizontalRule/Vue/index.html
new file mode 100644
index 00000000..a5180eed
--- /dev/null
+++ b/demos/src/Nodes/HorizontalRule/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/HorizontalRule/Vue/index.spec.js b/demos/src/Nodes/HorizontalRule/Vue/index.spec.js
new file mode 100644
index 00000000..0013e305
--- /dev/null
+++ b/demos/src/Nodes/HorizontalRule/Vue/index.spec.js
@@ -0,0 +1,66 @@
+context('/demos/Nodes/HorizontalRule', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/HorizontalRule')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ })
+ })
+
+ it('should parse horizontal rules correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ expect(editor.getHTML()).to.eq('Example Text
')
+ })
+ })
+
+ it('should parse horizontal rules with self-closing tag correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ expect(editor.getHTML()).to.eq('Example Text
')
+ })
+ })
+
+ it('the button should add a horizontal rule', () => {
+ cy.get('.ProseMirror hr')
+ .should('not.exist')
+
+ cy.get('button:first')
+ .click()
+
+ cy.get('.ProseMirror hr')
+ .should('exist')
+ })
+
+ it('the default markdown shortcut should add a horizontal rule', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+
+ cy.get('.ProseMirror hr')
+ .should('not.exist')
+
+ cy.get('.ProseMirror')
+ .type('---')
+
+ cy.get('.ProseMirror hr')
+ .should('exist')
+ })
+ })
+
+ it('the alternative markdown shortcut should add a horizontal rule', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+
+ cy.get('.ProseMirror hr')
+ .should('not.exist')
+
+ cy.get('.ProseMirror')
+ .type('___ ')
+
+ cy.get('.ProseMirror hr')
+ .should('exist')
+ })
+ })
+})
diff --git a/demos/src/Nodes/HorizontalRule/Vue/index.vue b/demos/src/Nodes/HorizontalRule/Vue/index.vue
new file mode 100644
index 00000000..5009a536
--- /dev/null
+++ b/demos/src/Nodes/HorizontalRule/Vue/index.vue
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Image/Vue/index.html b/demos/src/Nodes/Image/Vue/index.html
new file mode 100644
index 00000000..409bdcf0
--- /dev/null
+++ b/demos/src/Nodes/Image/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Image/Vue/index.spec.js b/demos/src/Nodes/Image/Vue/index.spec.js
new file mode 100644
index 00000000..f2357782
--- /dev/null
+++ b/demos/src/Nodes/Image/Vue/index.spec.js
@@ -0,0 +1,27 @@
+context('/demos/Nodes/Image', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/Image')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ cy.get('.ProseMirror').type('{selectall}')
+ })
+ })
+
+ it('should add an img tag with the correct URL', () => {
+ cy.window().then(win => {
+ cy.stub(win, 'prompt').returns('foobar.png')
+
+ cy.get('button:first')
+ .click()
+
+ cy.window().its('prompt').should('be.called')
+
+ cy.get('.ProseMirror')
+ .find('img')
+ .should('have.attr', 'src', 'foobar.png')
+ })
+ })
+})
diff --git a/demos/src/Nodes/Image/Vue/index.vue b/demos/src/Nodes/Image/Vue/index.vue
new file mode 100644
index 00000000..1a9bb5d8
--- /dev/null
+++ b/demos/src/Nodes/Image/Vue/index.vue
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/ListItem/Vue/index.html b/demos/src/Nodes/ListItem/Vue/index.html
new file mode 100644
index 00000000..14547a1c
--- /dev/null
+++ b/demos/src/Nodes/ListItem/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/ListItem/Vue/index.spec.js b/demos/src/Nodes/ListItem/Vue/index.spec.js
new file mode 100644
index 00000000..6c3cea43
--- /dev/null
+++ b/demos/src/Nodes/ListItem/Vue/index.spec.js
@@ -0,0 +1,49 @@
+context('/demos/Nodes/ListItem', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/ListItem')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('')
+ })
+ })
+
+ it('should add a new list item on Enter', () => {
+ cy.get('.ProseMirror')
+ .type('{enter}2nd Item')
+
+ cy.get('.ProseMirror')
+ .find('li:nth-child(1)')
+ .should('contain', 'Example Text')
+
+ cy.get('.ProseMirror')
+ .find('li:nth-child(2)')
+ .should('contain', '2nd Item')
+ })
+
+ it('should sink the list item on Tab', () => {
+ cy.get('.ProseMirror')
+ .type('{enter}')
+ .trigger('keydown', { key: 'Tab' })
+
+ cy.get('.ProseMirror').type('2nd Level')
+
+ cy.get('.ProseMirror')
+ .find('li:nth-child(1) li')
+ .should('contain', '2nd Level')
+ })
+
+ it('should lift the list item on Shift+Tab', () => {
+ cy.get('.ProseMirror')
+ .type('{enter}')
+ .trigger('keydown', { key: 'Tab' })
+ .trigger('keydown', { shiftKey: true, key: 'Tab' })
+
+ cy.get('.ProseMirror').type('1st Level')
+
+ cy.get('.ProseMirror')
+ .find('li:nth-child(2)')
+ .should('contain', '1st Level')
+ })
+})
diff --git a/demos/src/Nodes/ListItem/Vue/index.vue b/demos/src/Nodes/ListItem/Vue/index.vue
new file mode 100644
index 00000000..23bd48af
--- /dev/null
+++ b/demos/src/Nodes/ListItem/Vue/index.vue
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Mention/Vue/MentionList.vue b/demos/src/Nodes/Mention/Vue/MentionList.vue
new file mode 100644
index 00000000..26437b84
--- /dev/null
+++ b/demos/src/Nodes/Mention/Vue/MentionList.vue
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Mention/Vue/index.html b/demos/src/Nodes/Mention/Vue/index.html
new file mode 100644
index 00000000..9193a809
--- /dev/null
+++ b/demos/src/Nodes/Mention/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Mention/Vue/index.spec.js b/demos/src/Nodes/Mention/Vue/index.spec.js
new file mode 100644
index 00000000..efe62a9a
--- /dev/null
+++ b/demos/src/Nodes/Mention/Vue/index.spec.js
@@ -0,0 +1,7 @@
+context('/demos/Nodes/Mention', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/Mention')
+ })
+
+ // TODO: Write tests
+})
diff --git a/demos/src/Nodes/Mention/Vue/index.vue b/demos/src/Nodes/Mention/Vue/index.vue
new file mode 100644
index 00000000..5d22fe54
--- /dev/null
+++ b/demos/src/Nodes/Mention/Vue/index.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/OrderedList/Vue/index.html b/demos/src/Nodes/OrderedList/Vue/index.html
new file mode 100644
index 00000000..407d81a3
--- /dev/null
+++ b/demos/src/Nodes/OrderedList/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/OrderedList/Vue/index.spec.js b/demos/src/Nodes/OrderedList/Vue/index.spec.js
new file mode 100644
index 00000000..d4f2704c
--- /dev/null
+++ b/demos/src/Nodes/OrderedList/Vue/index.spec.js
@@ -0,0 +1,131 @@
+context('/demos/Nodes/OrderedList', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/OrderedList')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ cy.get('.ProseMirror').type('{selectall}')
+ })
+ })
+
+ it('should parse ordered lists correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ expect(editor.getHTML()).to.eq('Example Text
')
+ })
+ })
+
+ it('should parse ordered 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 ordered list item', () => {
+ cy.get('.ProseMirror ol')
+ .should('not.exist')
+
+ cy.get('.ProseMirror ol li')
+ .should('not.exist')
+
+ cy.get('button:nth-child(1)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('ol')
+ .should('contain', 'Example Text')
+
+ cy.get('.ProseMirror')
+ .find('ol li')
+ .should('contain', 'Example Text')
+ })
+
+ it('the button should toggle the ordered list', () => {
+ cy.get('.ProseMirror ol')
+ .should('not.exist')
+
+ cy.get('button:nth-child(1)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('ol')
+ .should('contain', 'Example Text')
+
+ cy.get('button:nth-child(1)')
+ .click()
+
+ cy.get('.ProseMirror ol')
+ .should('not.exist')
+ })
+
+ it('should make the paragraph an ordered list keyboard shortcut is pressed', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, shiftKey: true, key: '7' })
+ .find('ol 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('1. 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 ordered list from a number', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+ })
+
+ cy.get('.ProseMirror')
+ .type('1. List Item 1{enter}List Item 2')
+
+ cy.get('.ProseMirror')
+ .find('li:nth-child(1)')
+ .should('contain', 'List Item 1')
+
+ cy.get('.ProseMirror')
+ .find('li:nth-child(2)')
+ .should('contain', 'List Item 2')
+ })
+
+ it('should make a ordered list from a number other than number one', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+ })
+
+ cy.get('.ProseMirror')
+ .type('2. List Item 1{enter}List Item 2')
+
+ cy.get('.ProseMirror')
+ .find('ol')
+ .should('have.attr', 'start', '2')
+ })
+
+ it('should remove the ordered list after pressing backspace', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+ })
+
+ cy.get('.ProseMirror')
+ .type('1. {backspace}Example')
+
+ cy.get('.ProseMirror')
+ .find('p')
+ .should('contain', '1. Example')
+ })
+})
diff --git a/demos/src/Nodes/OrderedList/Vue/index.vue b/demos/src/Nodes/OrderedList/Vue/index.vue
new file mode 100644
index 00000000..885b0d0e
--- /dev/null
+++ b/demos/src/Nodes/OrderedList/Vue/index.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Paragraph/Vue/index.html b/demos/src/Nodes/Paragraph/Vue/index.html
new file mode 100644
index 00000000..e6a9b6c9
--- /dev/null
+++ b/demos/src/Nodes/Paragraph/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Paragraph/Vue/index.spec.js b/demos/src/Nodes/Paragraph/Vue/index.spec.js
new file mode 100644
index 00000000..3286da04
--- /dev/null
+++ b/demos/src/Nodes/Paragraph/Vue/index.spec.js
@@ -0,0 +1,58 @@
+context('/demos/Nodes/Paragraph', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/Paragraph')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+ })
+ })
+
+ it('should parse paragraphs correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ expect(editor.getHTML()).to.eq('Example Text
')
+
+ editor.commands.setContent('Example Text
')
+ expect(editor.getHTML()).to.eq('Example Text
')
+
+ editor.commands.setContent('Example Text
')
+ expect(editor.getHTML()).to.eq('Example Text
')
+ })
+ })
+
+ it('text should be wrapped in a paragraph by default', () => {
+ cy.get('.ProseMirror')
+ .type('Example Text')
+ .find('p')
+ .should('contain', 'Example Text')
+ })
+
+ it('enter should make a new paragraph', () => {
+ cy.get('.ProseMirror')
+ .type('First Paragraph{enter}Second Paragraph')
+ .find('p')
+ .should('have.length', 2)
+
+ cy.get('.ProseMirror')
+ .find('p:first')
+ .should('contain', 'First Paragraph')
+
+ cy.get('.ProseMirror')
+ .find('p:nth-child(2)')
+ .should('contain', 'Second Paragraph')
+ })
+
+ it('backspace should remove the second paragraph', () => {
+ cy.get('.ProseMirror')
+ .type('{enter}')
+ .find('p')
+ .should('have.length', 2)
+
+ cy.get('.ProseMirror')
+ .type('{backspace}')
+ .find('p')
+ .should('have.length', 1)
+ })
+})
diff --git a/demos/src/Nodes/Paragraph/Vue/index.vue b/demos/src/Nodes/Paragraph/Vue/index.vue
new file mode 100644
index 00000000..69a9ebe7
--- /dev/null
+++ b/demos/src/Nodes/Paragraph/Vue/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Table/Vue/index.html b/demos/src/Nodes/Table/Vue/index.html
new file mode 100644
index 00000000..4808cedf
--- /dev/null
+++ b/demos/src/Nodes/Table/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Table/Vue/index.spec.js b/demos/src/Nodes/Table/Vue/index.spec.js
new file mode 100644
index 00000000..75f20351
--- /dev/null
+++ b/demos/src/Nodes/Table/Vue/index.spec.js
@@ -0,0 +1,77 @@
+context('/demos/Nodes/Table', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/Table')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+ })
+ })
+
+ it('creates a table (1x1)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable({ cols: 1, rows: 1, withHeaderRow: false })
+
+ cy.get('.ProseMirror').find('td').its('length').should('eq', 1)
+ cy.get('.ProseMirror').find('tr').its('length').should('eq', 1)
+ })
+ })
+
+ it('creates a table (3x1)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable({ cols: 3, rows: 1, withHeaderRow: false })
+
+ cy.get('.ProseMirror').find('td').its('length').should('eq', 3)
+ cy.get('.ProseMirror').find('tr').its('length').should('eq', 1)
+ })
+ })
+
+ it('creates a table (1x3)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable({ cols: 1, rows: 3, withHeaderRow: false })
+
+ cy.get('.ProseMirror').find('td').its('length').should('eq', 3)
+ cy.get('.ProseMirror').find('tr').its('length').should('eq', 3)
+ })
+ })
+
+ it('creates a table with header row (1x3)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable({ cols: 1, rows: 3, withHeaderRow: true })
+
+ cy.get('.ProseMirror').find('th').its('length').should('eq', 1)
+ cy.get('.ProseMirror').find('td').its('length').should('eq', 2)
+ cy.get('.ProseMirror').find('tr').its('length').should('eq', 3)
+ })
+ })
+
+ it('creates a table with correct defaults (3x3, th)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable()
+
+ cy.get('.ProseMirror').find('th').its('length').should('eq', 3)
+ cy.get('.ProseMirror').find('td').its('length').should('eq', 6)
+ cy.get('.ProseMirror').find('tr').its('length').should('eq', 3)
+ })
+ })
+
+ it('generates correct markup for a table (1x1)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable({ cols: 1, rows: 1, withHeaderRow: false })
+
+ const html = editor.getHTML()
+ expect(html).to.equal('')
+ })
+ })
+
+ it('generates correct markup for a table (1x1, th)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable({ cols: 1, rows: 1, withHeaderRow: true })
+
+ const html = editor.getHTML()
+ expect(html).to.equal('')
+ })
+ })
+
+})
diff --git a/demos/src/Nodes/Table/Vue/index.vue b/demos/src/Nodes/Table/Vue/index.vue
new file mode 100644
index 00000000..739b3037
--- /dev/null
+++ b/demos/src/Nodes/Table/Vue/index.vue
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/TaskItem/Vue/index.html b/demos/src/Nodes/TaskItem/Vue/index.html
new file mode 100644
index 00000000..238184d5
--- /dev/null
+++ b/demos/src/Nodes/TaskItem/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/TaskItem/Vue/index.spec.js b/demos/src/Nodes/TaskItem/Vue/index.spec.js
new file mode 100644
index 00000000..49bf6ab2
--- /dev/null
+++ b/demos/src/Nodes/TaskItem/Vue/index.spec.js
@@ -0,0 +1,7 @@
+context('/demos/Nodes/TaskItem', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/TaskItem')
+ })
+
+ // TODO: Write tests
+})
diff --git a/demos/src/Nodes/TaskItem/Vue/index.vue b/demos/src/Nodes/TaskItem/Vue/index.vue
new file mode 100644
index 00000000..c46155f1
--- /dev/null
+++ b/demos/src/Nodes/TaskItem/Vue/index.vue
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/TaskList/Vue/index.html b/demos/src/Nodes/TaskList/Vue/index.html
new file mode 100644
index 00000000..36c537ec
--- /dev/null
+++ b/demos/src/Nodes/TaskList/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/TaskList/Vue/index.spec.js b/demos/src/Nodes/TaskList/Vue/index.spec.js
new file mode 100644
index 00000000..ac9d6acb
--- /dev/null
+++ b/demos/src/Nodes/TaskList/Vue/index.spec.js
@@ -0,0 +1,126 @@
+context('/demos/Nodes/TaskList', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/TaskList')
+ })
+
+ 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('')
+ expect(editor.getHTML()).to.eq('')
+ })
+ })
+
+ it('should parse unordered lists without paragraphs correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('')
+ expect(editor.getHTML()).to.eq('')
+ })
+ })
+
+ 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/Vue/index.vue b/demos/src/Nodes/TaskList/Vue/index.vue
new file mode 100644
index 00000000..342d9d00
--- /dev/null
+++ b/demos/src/Nodes/TaskList/Vue/index.vue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Text/Vue/index.html b/demos/src/Nodes/Text/Vue/index.html
new file mode 100644
index 00000000..b8670283
--- /dev/null
+++ b/demos/src/Nodes/Text/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Text/Vue/index.spec.js b/demos/src/Nodes/Text/Vue/index.spec.js
new file mode 100644
index 00000000..76b06242
--- /dev/null
+++ b/demos/src/Nodes/Text/Vue/index.spec.js
@@ -0,0 +1,18 @@
+context('/demos/Nodes/Text', () => {
+ before(() => {
+ cy.visit('/demos/Nodes/Text')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+ })
+ })
+
+ it('text should be wrapped in a paragraph by default', () => {
+ cy.get('.ProseMirror')
+ .type('Example Text')
+ .find('p')
+ .should('contain', 'Example Text')
+ })
+})
diff --git a/demos/src/Nodes/Text/Vue/index.vue b/demos/src/Nodes/Text/Vue/index.vue
new file mode 100644
index 00000000..8ae332ec
--- /dev/null
+++ b/demos/src/Nodes/Text/Vue/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+