diff --git a/demos/src/Experiments/Commands/Vue/CommandsList.vue b/demos/src/Experiments/Commands/Vue/CommandsList.vue
index 3c72c13f..8465d2dc 100644
--- a/demos/src/Experiments/Commands/Vue/CommandsList.vue
+++ b/demos/src/Experiments/Commands/Vue/CommandsList.vue
@@ -81,7 +81,7 @@ export default {
}
-
diff --git a/demos/src/Extensions/CharacterCount/Vue/index.html b/demos/src/Extensions/CharacterCount/Vue/index.html
new file mode 100644
index 00000000..7a9b01b9
--- /dev/null
+++ b/demos/src/Extensions/CharacterCount/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/CharacterCount/Vue/index.vue b/demos/src/Extensions/CharacterCount/Vue/index.vue
new file mode 100644
index 00000000..2003a491
--- /dev/null
+++ b/demos/src/Extensions/CharacterCount/Vue/index.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+ {{ editor.getCharacterCount() }}/{{ limit }} characters
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Collaboration/Vue/index.html b/demos/src/Extensions/Collaboration/Vue/index.html
new file mode 100644
index 00000000..96dbc27f
--- /dev/null
+++ b/demos/src/Extensions/Collaboration/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Collaboration/Vue/index.spec.js b/demos/src/Extensions/Collaboration/Vue/index.spec.js
new file mode 100644
index 00000000..494f1ee4
--- /dev/null
+++ b/demos/src/Extensions/Collaboration/Vue/index.spec.js
@@ -0,0 +1,7 @@
+context('/demos/Extensions/Collaboration', () => {
+ before(() => {
+ cy.visit('/demos/Extensions/Collaboration')
+ })
+
+ // TODO: Write tests
+})
diff --git a/demos/src/Extensions/Collaboration/Vue/index.vue b/demos/src/Extensions/Collaboration/Vue/index.vue
new file mode 100644
index 00000000..613d5d24
--- /dev/null
+++ b/demos/src/Extensions/Collaboration/Vue/index.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
diff --git a/demos/src/Extensions/CollaborationCursor/Vue/index.html b/demos/src/Extensions/CollaborationCursor/Vue/index.html
new file mode 100644
index 00000000..474777cd
--- /dev/null
+++ b/demos/src/Extensions/CollaborationCursor/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/CollaborationCursor/Vue/index.spec.js b/demos/src/Extensions/CollaborationCursor/Vue/index.spec.js
new file mode 100644
index 00000000..29501e66
--- /dev/null
+++ b/demos/src/Extensions/CollaborationCursor/Vue/index.spec.js
@@ -0,0 +1,7 @@
+context('/demos/Extensions/CollaborationCursor', () => {
+ before(() => {
+ cy.visit('/demos/Extensions/CollaborationCursor')
+ })
+
+ // TODO: Write tests
+})
diff --git a/demos/src/Extensions/CollaborationCursor/Vue/index.vue b/demos/src/Extensions/CollaborationCursor/Vue/index.vue
new file mode 100644
index 00000000..f2484d5f
--- /dev/null
+++ b/demos/src/Extensions/CollaborationCursor/Vue/index.vue
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Color/Vue/index.html b/demos/src/Extensions/Color/Vue/index.html
new file mode 100644
index 00000000..e9251629
--- /dev/null
+++ b/demos/src/Extensions/Color/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Color/Vue/index.spec.js b/demos/src/Extensions/Color/Vue/index.spec.js
new file mode 100644
index 00000000..544712e5
--- /dev/null
+++ b/demos/src/Extensions/Color/Vue/index.spec.js
@@ -0,0 +1,53 @@
+context('/demos/Extensions/Color', () => {
+ before(() => {
+ cy.visit('/demos/Extensions/Color')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ })
+ cy.get('.ProseMirror').type('{selectall}')
+ })
+
+ it('should set the color of the selected text', () => {
+ cy.get('button:first')
+ .should('not.have.class', 'is-active')
+ .click()
+ .should('have.class', 'is-active')
+
+ cy.get('.ProseMirror')
+ .find('span')
+ .should('have.attr', 'style', 'color: #958DF1')
+ })
+
+ it('should remove the color of the selected text', () => {
+ cy.get('button:first')
+ .click()
+
+ cy.get('.ProseMirror span').should('exist')
+
+ cy.get('button:last')
+ .click()
+
+ cy.get('.ProseMirror span').should('not.exist')
+ })
+
+ it('should change text color with color picker', () => {
+ cy.get('input[type=color]')
+ .invoke('val', '#ff0000')
+ .trigger('input')
+
+ cy.get('.ProseMirror')
+ .find('span')
+ .should('have.attr', 'style', 'color: #ff0000')
+ })
+
+ it('should match text and color picker color values', () => {
+ cy.get('button:first')
+ .click()
+
+ cy.get('input[type=color]')
+ .should('have.value', '#958df1')
+ })
+})
diff --git a/demos/src/Extensions/Color/Vue/index.vue b/demos/src/Extensions/Color/Vue/index.vue
new file mode 100644
index 00000000..25457743
--- /dev/null
+++ b/demos/src/Extensions/Color/Vue/index.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Dropcursor/Vue/index.html b/demos/src/Extensions/Dropcursor/Vue/index.html
new file mode 100644
index 00000000..976680c0
--- /dev/null
+++ b/demos/src/Extensions/Dropcursor/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Dropcursor/Vue/index.spec.js b/demos/src/Extensions/Dropcursor/Vue/index.spec.js
new file mode 100644
index 00000000..2e48f420
--- /dev/null
+++ b/demos/src/Extensions/Dropcursor/Vue/index.spec.js
@@ -0,0 +1,7 @@
+context('/demos/Examples/Dropcursor', () => {
+ before(() => {
+ cy.visit('/demos/Examples/Dropcursor')
+ })
+
+ // TODO: Write tests
+})
diff --git a/demos/src/Extensions/Dropcursor/Vue/index.vue b/demos/src/Extensions/Dropcursor/Vue/index.vue
new file mode 100644
index 00000000..0b28a32a
--- /dev/null
+++ b/demos/src/Extensions/Dropcursor/Vue/index.vue
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/FloatingMenu/React/index.jsx b/demos/src/Extensions/FloatingMenu/React/index.jsx
new file mode 100644
index 00000000..d2870c45
--- /dev/null
+++ b/demos/src/Extensions/FloatingMenu/React/index.jsx
@@ -0,0 +1,44 @@
+import React from 'react'
+import { useEditor, EditorContent, FloatingMenu } from '@tiptap/react'
+import StarterKit from '@tiptap/starter-kit'
+import './styles.scss'
+
+export default () => {
+ const editor = useEditor({
+ extensions: [
+ StarterKit,
+ ],
+ content: `
+
+ This is an example of a Medium-like editor. Enter a new line and some buttons will appear.
+
+
+ `,
+ })
+
+ return (
+ <>
+ {editor &&
+
+
+
+ }
+
+ >
+ )
+}
diff --git a/demos/src/Extensions/FloatingMenu/React/styles.scss b/demos/src/Extensions/FloatingMenu/React/styles.scss
new file mode 100644
index 00000000..9489311c
--- /dev/null
+++ b/demos/src/Extensions/FloatingMenu/React/styles.scss
@@ -0,0 +1,10 @@
+.ProseMirror {
+ > * + * {
+ margin-top: 0.75em;
+ }
+
+ ul,
+ ol {
+ padding: 0 1rem;
+ }
+}
diff --git a/demos/src/Extensions/FloatingMenu/Vue/index.html b/demos/src/Extensions/FloatingMenu/Vue/index.html
new file mode 100644
index 00000000..bdba5b9e
--- /dev/null
+++ b/demos/src/Extensions/FloatingMenu/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/FloatingMenu/Vue/index.vue b/demos/src/Extensions/FloatingMenu/Vue/index.vue
new file mode 100644
index 00000000..a5c2d222
--- /dev/null
+++ b/demos/src/Extensions/FloatingMenu/Vue/index.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Focus/Vue/index.html b/demos/src/Extensions/Focus/Vue/index.html
new file mode 100644
index 00000000..90f7808a
--- /dev/null
+++ b/demos/src/Extensions/Focus/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Focus/Vue/index.spec.js b/demos/src/Extensions/Focus/Vue/index.spec.js
new file mode 100644
index 00000000..995da60f
--- /dev/null
+++ b/demos/src/Extensions/Focus/Vue/index.spec.js
@@ -0,0 +1,9 @@
+context('/demos/Extensions/Focus', () => {
+ before(() => {
+ cy.visit('/demos/Extensions/Focus')
+ })
+
+ it('should have class', () => {
+ cy.get('.ProseMirror p:first').should('have.class', 'has-focus')
+ })
+})
diff --git a/demos/src/Extensions/Focus/Vue/index.vue b/demos/src/Extensions/Focus/Vue/index.vue
new file mode 100644
index 00000000..2423dd96
--- /dev/null
+++ b/demos/src/Extensions/Focus/Vue/index.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/FontFamily/Vue/index.html b/demos/src/Extensions/FontFamily/Vue/index.html
new file mode 100644
index 00000000..c21f4c9e
--- /dev/null
+++ b/demos/src/Extensions/FontFamily/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/FontFamily/Vue/index.spec.js b/demos/src/Extensions/FontFamily/Vue/index.spec.js
new file mode 100644
index 00000000..51dd2f4c
--- /dev/null
+++ b/demos/src/Extensions/FontFamily/Vue/index.spec.js
@@ -0,0 +1,7 @@
+context('/demos/Extensions/FontFamily', () => {
+ before(() => {
+ cy.visit('/demos/Extensions/FontFamily')
+ })
+
+ // TODO: Write tests
+})
diff --git a/demos/src/Extensions/FontFamily/Vue/index.vue b/demos/src/Extensions/FontFamily/Vue/index.vue
new file mode 100644
index 00000000..73695593
--- /dev/null
+++ b/demos/src/Extensions/FontFamily/Vue/index.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Gapcursor/Vue/index.html b/demos/src/Extensions/Gapcursor/Vue/index.html
new file mode 100644
index 00000000..a59ea8cb
--- /dev/null
+++ b/demos/src/Extensions/Gapcursor/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Gapcursor/Vue/index.spec.js b/demos/src/Extensions/Gapcursor/Vue/index.spec.js
new file mode 100644
index 00000000..1ed8bc13
--- /dev/null
+++ b/demos/src/Extensions/Gapcursor/Vue/index.spec.js
@@ -0,0 +1,7 @@
+context('/demos/Examples/Gapcursor', () => {
+ before(() => {
+ cy.visit('/demos/Examples/Gapcursor')
+ })
+
+ // TODO: Write tests
+})
diff --git a/demos/src/Extensions/Gapcursor/Vue/index.vue b/demos/src/Extensions/Gapcursor/Vue/index.vue
new file mode 100644
index 00000000..6fe32275
--- /dev/null
+++ b/demos/src/Extensions/Gapcursor/Vue/index.vue
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/History/Vue/index.html b/demos/src/Extensions/History/Vue/index.html
new file mode 100644
index 00000000..cf37e046
--- /dev/null
+++ b/demos/src/Extensions/History/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/History/Vue/index.spec.js b/demos/src/Extensions/History/Vue/index.spec.js
new file mode 100644
index 00000000..79999b7f
--- /dev/null
+++ b/demos/src/Extensions/History/Vue/index.spec.js
@@ -0,0 +1,123 @@
+context('/demos/Extensions/History', () => {
+ beforeEach(() => {
+ cy.visit('/demos/Extensions/History')
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Mistake
')
+ })
+ })
+
+ it('should make the last change undone', () => {
+ cy.get('.ProseMirror')
+ .should('contain', 'Mistake')
+
+ cy.get('button:first')
+ .should('not.have.attr', 'disabled')
+
+ cy.get('button:first')
+ .click()
+
+ cy.get('.ProseMirror')
+ .should('not.contain', 'Mistake')
+ })
+
+ it('should make the last change undone with the keyboard shortcut', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, key: 'z' })
+
+ cy.get('.ProseMirror')
+ .should('not.contain', 'Mistake')
+ })
+
+ it('should make the last change undone with the keyboard shortcut (russian)', () => {
+ cy.get('.ProseMirror')
+ .should('contain', 'Mistake')
+
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, key: 'я' })
+
+ cy.get('.ProseMirror')
+ .should('not.contain', 'Mistake')
+ })
+
+ it('should apply the last undone change again with the keyboard shortcut', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, key: 'z' })
+
+ cy.get('.ProseMirror')
+ .should('not.contain', 'Mistake')
+
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, shiftKey: true, key: 'z' })
+
+ cy.get('.ProseMirror')
+ .should('contain', 'Mistake')
+ })
+
+ it('should apply the last undone change again with the keyboard shortcut (russian)', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, key: 'я' })
+
+ cy.get('.ProseMirror')
+ .should('not.contain', 'Mistake')
+
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, shiftKey: true, key: 'я' })
+
+ cy.get('.ProseMirror')
+ .should('contain', 'Mistake')
+ })
+
+ it('should apply the last undone change again', () => {
+ cy.get('.ProseMirror')
+ .should('contain', 'Mistake')
+
+ cy.get('button:first')
+ .should('not.have.attr', 'disabled')
+
+ cy.get('button:first')
+ .click()
+
+ cy.get('.ProseMirror')
+ .should('not.contain', 'Mistake')
+
+ cy.get('button:first')
+ .should('have.attr', 'disabled')
+
+ cy.get('button:nth-child(2)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .should('contain', 'Mistake')
+ })
+
+ it('should disable undo button when there are no more changes to undo', () => {
+ cy.get('.ProseMirror')
+ .should('contain', 'Mistake')
+
+ cy.get('button:first')
+ .should('not.have.attr', 'disabled')
+
+ cy.get('button:first')
+ .click()
+
+ cy.get('button:first')
+ .should('have.attr', 'disabled')
+ })
+
+ it('should disable redo button when there are no more changes to redo', () => {
+ cy.get('.ProseMirror')
+ .should('contain', 'Mistake')
+
+ cy.get('button:nth-child(2)')
+ .should('have.attr', 'disabled')
+
+ cy.get('button:first')
+ .should('not.have.attr', 'disabled')
+
+ cy.get('button:first')
+ .click()
+
+ cy.get('button:nth-child(2)')
+ .should('not.have.attr', 'disabled')
+ })
+})
diff --git a/demos/src/Extensions/History/Vue/index.vue b/demos/src/Extensions/History/Vue/index.vue
new file mode 100644
index 00000000..5adcf66a
--- /dev/null
+++ b/demos/src/Extensions/History/Vue/index.vue
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Placeholder/Vue/index.html b/demos/src/Extensions/Placeholder/Vue/index.html
new file mode 100644
index 00000000..c4e1d9b6
--- /dev/null
+++ b/demos/src/Extensions/Placeholder/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Placeholder/Vue/index.vue b/demos/src/Extensions/Placeholder/Vue/index.vue
new file mode 100644
index 00000000..c27df46e
--- /dev/null
+++ b/demos/src/Extensions/Placeholder/Vue/index.vue
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/TextAlign/Vue/index.html b/demos/src/Extensions/TextAlign/Vue/index.html
new file mode 100644
index 00000000..ed18dbb4
--- /dev/null
+++ b/demos/src/Extensions/TextAlign/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/TextAlign/Vue/index.spec.js b/demos/src/Extensions/TextAlign/Vue/index.spec.js
new file mode 100644
index 00000000..65f40f8e
--- /dev/null
+++ b/demos/src/Extensions/TextAlign/Vue/index.spec.js
@@ -0,0 +1,112 @@
+context('/demos/Extensions/TextAlign', () => {
+ before(() => {
+ cy.visit('/demos/Extensions/TextAlign')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ })
+ })
+
+ it('should parse left align text correctly (and not render)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ expect(editor.getHTML()).to.eq('Example Text
')
+ })
+ })
+
+ it('should parse center align text correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ expect(editor.getHTML()).to.eq('Example Text
')
+ })
+ })
+
+ it('should parse right align text correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ expect(editor.getHTML()).to.eq('Example Text
')
+ })
+ })
+
+ it('should parse left justify text correctly', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('Example Text
')
+ expect(editor.getHTML()).to.eq('Example Text
')
+ })
+ })
+
+ it('aligns the text left on the 1st button', () => {
+ cy.get('button:nth-child(1)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('p')
+ .should('not.have.css', 'text-align', 'left')
+ })
+
+ it('aligns the text center on the 2nd button', () => {
+ cy.get('button:nth-child(2)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('p')
+ .should('have.css', 'text-align', 'center')
+ })
+
+ it('aligns the text right on the 3rd button', () => {
+ cy.get('button:nth-child(3)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('p')
+ .should('have.css', 'text-align', 'right')
+ })
+
+ it('aligns the text justified on the 4th button', () => {
+ cy.get('button:nth-child(4)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('p')
+ .should('have.css', 'text-align', 'justify')
+ })
+
+ it('aligns the text default on the 5th button', () => {
+ cy.get('button:nth-child(5)')
+ .click()
+
+ cy.get('.ProseMirror')
+ .find('p')
+ .should('not.have.css', 'text-align', 'left')
+ })
+
+ it('aligns the text left when pressing the keyboard shortcut', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, shiftKey: true, key: 'l' })
+ .find('p')
+ .should('not.have.css', 'text-align', 'left')
+ })
+
+ it('aligns the text center when pressing the keyboard shortcut', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, shiftKey: true, key: 'e' })
+ .find('p')
+ .should('have.css', 'text-align', 'center')
+ })
+
+ it('aligns the text right when pressing the keyboard shortcut', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, shiftKey: true, key: 'r' })
+ .find('p')
+ .should('have.css', 'text-align', 'right')
+ })
+
+ it('aligns the text justified when pressing the keyboard shortcut', () => {
+ cy.get('.ProseMirror')
+ .trigger('keydown', { modKey: true, shiftKey: true, key: 'j' })
+ .find('p')
+ .should('have.css', 'text-align', 'justify')
+ })
+})
diff --git a/demos/src/Extensions/TextAlign/Vue/index.vue b/demos/src/Extensions/TextAlign/Vue/index.vue
new file mode 100644
index 00000000..10b46b04
--- /dev/null
+++ b/demos/src/Extensions/TextAlign/Vue/index.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Typography/Vue/index.html b/demos/src/Extensions/Typography/Vue/index.html
new file mode 100644
index 00000000..74047059
--- /dev/null
+++ b/demos/src/Extensions/Typography/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Extensions/Typography/Vue/index.spec.js b/demos/src/Extensions/Typography/Vue/index.spec.js
new file mode 100644
index 00000000..2ad57c82
--- /dev/null
+++ b/demos/src/Extensions/Typography/Vue/index.spec.js
@@ -0,0 +1,131 @@
+context('/demos/Extensions/Typography', () => {
+ before(() => {
+ cy.visit('/demos/Extensions/Typography')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+ })
+ })
+
+ it('should make an em dash from two dashes', () => {
+ cy.get('.ProseMirror')
+ .type('-- emDash')
+ .should('contain', '— emDash')
+ })
+
+ it('should make an ellipsis from three dots', () => {
+ cy.get('.ProseMirror')
+ .type('... ellipsis')
+ .should('contain', '… ellipsis')
+ })
+
+ it('should make a correct open double quote', () => {
+ cy.get('.ProseMirror')
+ .type('"openDoubleQuote"')
+ .should('contain', '“openDoubleQuote')
+ })
+
+ it('should make a correct close double quote', () => {
+ cy.get('.ProseMirror')
+ .type('"closeDoubleQuote"')
+ .should('contain', 'closeDoubleQuote”')
+ })
+
+ it('should make a correct open single quote', () => {
+ cy.get('.ProseMirror')
+ .type("'openSingleQuote'")
+ .should('contain', '‘openSingleQuote’')
+ })
+
+ it('should make a correct close single quote', () => {
+ cy.get('.ProseMirror')
+ .type("'closeSingleQuote'")
+ .should('contain', 'closeSingleQuote’')
+ })
+
+ it('should make a left arrow', () => {
+ cy.get('.ProseMirror')
+ .type('<- leftArrow')
+ .should('contain', '← leftArrow')
+ })
+
+ it('should make a right arrow', () => {
+ cy.get('.ProseMirror')
+ .type('-> rightArrow')
+ .should('contain', '→ rightArrow')
+ })
+
+ it('should make a copyright sign', () => {
+ cy.get('.ProseMirror')
+ .type('(c) copyright')
+ .should('contain', '© copyright')
+ })
+
+ it('should make a registered trademark sign', () => {
+ cy.get('.ProseMirror')
+ .type('(r) registeredTrademark')
+ .should('contain', '® registeredTrademark')
+ })
+
+ it('should make a trademark sign', () => {
+ cy.get('.ProseMirror')
+ .type('(tm) trademark')
+ .should('contain', '™ trademark')
+ })
+
+ it('should make a one half', () => {
+ cy.get('.ProseMirror')
+ .type('1/2 oneHalf')
+ .should('contain', '½ oneHalf')
+ })
+
+ it('should make a plus/minus sign', () => {
+ cy.get('.ProseMirror')
+ .type('+/- plusMinus')
+ .should('contain', '± plusMinus')
+ })
+
+ it('should make a not equal sign', () => {
+ cy.get('.ProseMirror')
+ .type('!= notEqual')
+ .should('contain', '≠ notEqual')
+ })
+
+ it('should make a laquo', () => {
+ cy.get('.ProseMirror')
+ .type('<< laquorow')
+ .should('contain', '« laquo')
+ })
+
+ it('should make a raquo', () => {
+ cy.get('.ProseMirror')
+ .type('>> raquorow')
+ .should('contain', '» raquo')
+ })
+
+ it('should make a multiplication sign from an asterisk', () => {
+ cy.get('.ProseMirror')
+ .type('1*1 multiplication')
+ .should('contain', '1×1 multiplication')
+ })
+
+ it('should make a multiplication sign from an x', () => {
+ cy.get('.ProseMirror')
+ .type('1x1 multiplication')
+ .should('contain', '1×1 multiplication')
+ })
+
+ it('should make a multiplication sign from an asterisk with spaces', () => {
+ cy.get('.ProseMirror')
+ .type('1 * 1 multiplication')
+ .should('contain', '1 × 1 multiplication')
+ })
+
+ it('should make a multiplication sign from an x with spaces', () => {
+ cy.get('.ProseMirror')
+ .type('1 x 1 multiplication')
+ .should('contain', '1 × 1 multiplication')
+ })
+})
diff --git a/demos/src/Extensions/Typography/Vue/index.vue b/demos/src/Extensions/Typography/Vue/index.vue
new file mode 100644
index 00000000..55cb211a
--- /dev/null
+++ b/demos/src/Extensions/Typography/Vue/index.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+