move everything around, add more content and a first test for images
This commit is contained in:
104
docs/src/demos/Nodes/Blockquote/index.spec.js
Normal file
104
docs/src/demos/Nodes/Blockquote/index.spec.js
Normal file
@@ -0,0 +1,104 @@
|
||||
context('/api/nodes/blockquote', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/nodes/blockquote')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example Text</p>')
|
||||
editor.selectAll()
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse blockquote tags correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<blockquote><p>Example Text</p></blockquote>')
|
||||
expect(editor.getHTML()).to.eq('<blockquote><p>Example Text</p></blockquote>')
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse blockquote tags without paragraphs correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<blockquote>Example Text</blockquote>')
|
||||
expect(editor.getHTML()).to.eq('<blockquote><p>Example Text</p></blockquote>')
|
||||
})
|
||||
})
|
||||
|
||||
it('the button should make the selected line a blockquote', () => {
|
||||
cy.get('.ProseMirror blockquote')
|
||||
.should('not.exist')
|
||||
|
||||
cy.get('.demo__preview 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.setContent('<p>Example Text</p><p>Example Text</p>')
|
||||
editor.selectAll()
|
||||
})
|
||||
|
||||
cy.get('.demo__preview 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('.demo__preview button:first')
|
||||
.click()
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.find('blockquote')
|
||||
.should('contain', 'Example Text')
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.type('{selectall}')
|
||||
|
||||
cy.get('.demo__preview button:first')
|
||||
.click()
|
||||
|
||||
cy.get('.ProseMirror blockquote')
|
||||
.should('not.exist')
|
||||
})
|
||||
|
||||
it('the keyboard shortcut should make the selected line a blockquote', () => {
|
||||
cy.get('.ProseMirror')
|
||||
.trigger('keydown', { shiftKey: true, modKey: true, key: '9' })
|
||||
.find('blockquote')
|
||||
.should('contain', 'Example Text')
|
||||
})
|
||||
|
||||
it('the keyboard shortcut should toggle the blockquote', () => {
|
||||
cy.get('.ProseMirror blockquote')
|
||||
.should('not.exist')
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.trigger('keydown', { shiftKey: true, modKey: true, key: '9' })
|
||||
.find('blockquote')
|
||||
.should('contain', 'Example Text')
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.type('{selectall}')
|
||||
.trigger('keydown', { shiftKey: true, modKey: true, key: '9' })
|
||||
|
||||
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')
|
||||
})
|
||||
})
|
||||
51
docs/src/demos/Nodes/Blockquote/index.vue
Normal file
51
docs/src/demos/Nodes/Blockquote/index.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<button @click="editor.chain().focus().blockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
||||
blockquote
|
||||
</button>
|
||||
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import Blockquote from '@tiptap/extension-blockquote'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
Blockquote(),
|
||||
],
|
||||
content: `
|
||||
<blockquote>
|
||||
Life is like riding a bycicle. To keep your balance, you must keep moving.
|
||||
</blockquote>
|
||||
<p>Albert Einstein</p>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
145
docs/src/demos/Nodes/BulletList/index.spec.js
Normal file
145
docs/src/demos/Nodes/BulletList/index.spec.js
Normal file
@@ -0,0 +1,145 @@
|
||||
context('/api/nodes/bullet-list', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/nodes/bullet-list')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example Text</p>')
|
||||
editor.selectAll()
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse unordered lists correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<ul><li><p>Example Text</p></li></ul>')
|
||||
expect(editor.getHTML()).to.eq('<ul><li><p>Example Text</p></li></ul>')
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse unordered lists without paragraphs correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<ul><li>Example Text</li></ul>')
|
||||
expect(editor.getHTML()).to.eq('<ul><li><p>Example Text</p></li></ul>')
|
||||
})
|
||||
})
|
||||
|
||||
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('.demo__preview 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('.demo__preview button:nth-child(1)')
|
||||
.click()
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.find('ul')
|
||||
.should('contain', 'Example Text')
|
||||
|
||||
cy.get('.demo__preview 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.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 bullet list from an asterisk', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.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.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.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.clearContent()
|
||||
})
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.type('* {backspace}Example')
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.find('p')
|
||||
.should('contain', '* Example')
|
||||
})
|
||||
})
|
||||
53
docs/src/demos/Nodes/BulletList/index.vue
Normal file
53
docs/src/demos/Nodes/BulletList/index.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<button @click="editor.chain().focus().bulletList().run()" :class="{ 'is-active': editor.isActive('bullet_list') }">
|
||||
bullet list
|
||||
</button>
|
||||
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import BulletList from '@tiptap/extension-bullet-list'
|
||||
import ListItem from '@tiptap/extension-list-item'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
BulletList(),
|
||||
ListItem(),
|
||||
],
|
||||
content: `
|
||||
<ul>
|
||||
<li>A list item</li>
|
||||
<li>And another one</li>
|
||||
</ul>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
128
docs/src/demos/Nodes/CodeBlock/index.spec.js
Normal file
128
docs/src/demos/Nodes/CodeBlock/index.spec.js
Normal file
@@ -0,0 +1,128 @@
|
||||
context('/api/nodes/code-block', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/nodes/code-block')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example Text</p>')
|
||||
editor.selectAll()
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse code blocks correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<pre><code>Example Text</code></pre>')
|
||||
expect(editor.getHTML()).to.eq('<pre><code>Example Text</code></pre>')
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse code blocks with language correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<pre><code class="language-css">Example Text</code></pre>')
|
||||
expect(editor.getHTML()).to.eq('<pre><code class="language-css">Example Text</code></pre>')
|
||||
})
|
||||
})
|
||||
|
||||
it('the button should make the selected line a code block', () => {
|
||||
cy.get('.demo__preview button:first')
|
||||
.click()
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.find('pre')
|
||||
.should('contain', 'Example Text')
|
||||
})
|
||||
|
||||
it('the button should toggle the code block', () => {
|
||||
cy.get('.demo__preview button:first')
|
||||
.click()
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.find('pre')
|
||||
.should('contain', 'Example Text')
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.type('{selectall}')
|
||||
|
||||
cy.get('.demo__preview 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', { shiftKey: true, modKey: true, key: 'c' })
|
||||
.find('pre')
|
||||
.should('contain', 'Example Text')
|
||||
})
|
||||
|
||||
it('the keyboard shortcut should toggle the code block', () => {
|
||||
cy.get('.ProseMirror')
|
||||
.trigger('keydown', { shiftKey: true, modKey: true, key: 'c' })
|
||||
.find('pre')
|
||||
.should('contain', 'Example Text')
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.type('{selectall}')
|
||||
.trigger('keydown', { shiftKey: true, modKey: 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.setContent('<pre><code class="language-css">body { display: none; }</code></pre>')
|
||||
|
||||
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.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.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.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.clearContent()
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.type('~~~js Code')
|
||||
.find('pre>code.language-js')
|
||||
.should('contain', 'Code')
|
||||
})
|
||||
})
|
||||
})
|
||||
64
docs/src/demos/Nodes/CodeBlock/index.vue
Normal file
64
docs/src/demos/Nodes/CodeBlock/index.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<button @click="editor.chain().focus().codeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
||||
code block
|
||||
</button>
|
||||
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import CodeBlock from '@tiptap/extension-code-block'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
CodeBlock(),
|
||||
],
|
||||
content: `
|
||||
<p>
|
||||
That’s a boring paragraph followed by a fenced code block:
|
||||
</p>
|
||||
<pre><code>for (var i=1; i <= 20; i++)
|
||||
{
|
||||
if (i % 15 == 0)
|
||||
console.log("FizzBuzz");
|
||||
else if (i % 3 == 0)
|
||||
console.log("Fizz");
|
||||
else if (i % 5 == 0)
|
||||
console.log("Buzz");
|
||||
else
|
||||
console.log(i);
|
||||
}</code></pre>
|
||||
<p>
|
||||
Press Command/Ctrl + Enter to leave the fenced code block and continue typing in boring paragraphs.
|
||||
</p>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
26
docs/src/demos/Nodes/Document/index.spec.js
Normal file
26
docs/src/demos/Nodes/Document/index.spec.js
Normal file
@@ -0,0 +1,26 @@
|
||||
context('/api/nodes/document', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/nodes/document')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p></p>')
|
||||
})
|
||||
})
|
||||
|
||||
it('should return the document in as json', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
const json = editor.getJSON()
|
||||
|
||||
expect(json).to.deep.equal({
|
||||
type: 'document',
|
||||
content: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
42
docs/src/demos/Nodes/Document/index.vue
Normal file
42
docs/src/demos/Nodes/Document/index.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
],
|
||||
content: `
|
||||
<p>The Document extension is required. Though, you can write your own implementation, e. g. to give it custom name.</p>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
58
docs/src/demos/Nodes/HardBreak/index.spec.js
Normal file
58
docs/src/demos/Nodes/HardBreak/index.spec.js
Normal file
@@ -0,0 +1,58 @@
|
||||
context('/api/nodes/hard-break', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/nodes/hard-break')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example Text</p>')
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse hard breaks correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example<br>Text</p>')
|
||||
expect(editor.getHTML()).to.eq('<p>Example<br>Text</p>')
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse hard breaks with self-closing tag correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example<br />Text</p>')
|
||||
expect(editor.getHTML()).to.eq('<p>Example<br>Text</p>')
|
||||
})
|
||||
})
|
||||
|
||||
it('the button should add a line break', () => {
|
||||
cy.get('.ProseMirror br')
|
||||
.should('not.exist')
|
||||
|
||||
cy.get('.demo__preview button:first')
|
||||
.click()
|
||||
|
||||
cy.get('.ProseMirror br')
|
||||
.should('exist')
|
||||
})
|
||||
|
||||
it.skip('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')
|
||||
})
|
||||
})
|
||||
57
docs/src/demos/Nodes/HardBreak/index.vue
Normal file
57
docs/src/demos/Nodes/HardBreak/index.vue
Normal file
@@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<button @click="editor.chain().focus().hardBreak().run()">
|
||||
hardBreak
|
||||
</button>
|
||||
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import HardBreak from '@tiptap/extension-hard-break'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
HardBreak(),
|
||||
],
|
||||
content: `
|
||||
<p>
|
||||
This<br>
|
||||
is<br>
|
||||
a<br>
|
||||
single<br>
|
||||
paragraph<br>
|
||||
with<br>
|
||||
line<br>
|
||||
breaks.
|
||||
</p>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
99
docs/src/demos/Nodes/Heading/index.spec.js
Normal file
99
docs/src/demos/Nodes/Heading/index.spec.js
Normal file
@@ -0,0 +1,99 @@
|
||||
context('/api/nodes/heading', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/nodes/heading')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example Text</p>')
|
||||
editor.selectAll()
|
||||
})
|
||||
})
|
||||
|
||||
const headings = [
|
||||
'<h1>Example Text</h1>',
|
||||
'<h2>Example Text</h2>',
|
||||
'<h3>Example Text</h3>',
|
||||
]
|
||||
|
||||
headings.forEach(html => {
|
||||
it(`should parse headings correctly (${html})`, () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent(html)
|
||||
expect(editor.getHTML()).to.eq(html)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('should omit disabled heading levels', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<h4>Example Text</h4>')
|
||||
expect(editor.getHTML()).to.eq('<p>Example Text</p>')
|
||||
})
|
||||
})
|
||||
|
||||
it('the button should make the selected line a h1', () => {
|
||||
cy.get('.ProseMirror h1')
|
||||
.should('not.exist')
|
||||
|
||||
cy.get('.demo__preview 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('.demo__preview 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('.demo__preview 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('.demo__preview button:nth-child(1)')
|
||||
.click()
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.find('h1')
|
||||
.should('contain', 'Example Text')
|
||||
|
||||
cy.get('.demo__preview button:nth-child(1)')
|
||||
.click()
|
||||
|
||||
cy.get('.ProseMirror h1')
|
||||
.should('not.exist')
|
||||
})
|
||||
|
||||
it('should make a heading from the default markdown shortcut', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.clearContent()
|
||||
})
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.type('# Headline')
|
||||
.find('h1')
|
||||
.should('contain', 'Headline')
|
||||
})
|
||||
})
|
||||
59
docs/src/demos/Nodes/Heading/index.vue
Normal file
59
docs/src/demos/Nodes/Heading/index.vue
Normal file
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<button @click="editor.chain().focus().heading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
||||
h1
|
||||
</button>
|
||||
<button @click="editor.chain().focus().heading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
||||
h2
|
||||
</button>
|
||||
<button @click="editor.chain().focus().heading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
||||
h3
|
||||
</button>
|
||||
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import Heading from '@tiptap/extension-heading'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
Heading({
|
||||
levels: [1, 2, 3],
|
||||
}),
|
||||
],
|
||||
content: `
|
||||
<h1>This is a 1st level heading</h1>
|
||||
<h2>This is a 2nd level heading</h2>
|
||||
<h3>This is a 3rd level heading</h3>
|
||||
<h4>This 4th level heading will be converted to a paragraph, because levels are configured to be only 1, 2 or 3.</h4>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
66
docs/src/demos/Nodes/HorizontalRule/index.spec.js
Normal file
66
docs/src/demos/Nodes/HorizontalRule/index.spec.js
Normal file
@@ -0,0 +1,66 @@
|
||||
context('/api/nodes/horizontal-rule', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/nodes/horizontal-rule')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example Text</p>')
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse horizontal rules correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example Text</p><hr>')
|
||||
expect(editor.getHTML()).to.eq('<p>Example Text</p><hr>')
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse horizontal rules with self-closing tag correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example Text</p><hr />')
|
||||
expect(editor.getHTML()).to.eq('<p>Example Text</p><hr>')
|
||||
})
|
||||
})
|
||||
|
||||
it('the button should add a horizontal rule', () => {
|
||||
cy.get('.ProseMirror hr')
|
||||
.should('not.exist')
|
||||
|
||||
cy.get('.demo__preview 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.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.clearContent()
|
||||
|
||||
cy.get('.ProseMirror hr')
|
||||
.should('not.exist')
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.type('___ ')
|
||||
|
||||
cy.get('.ProseMirror hr')
|
||||
.should('exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
52
docs/src/demos/Nodes/HorizontalRule/index.vue
Normal file
52
docs/src/demos/Nodes/HorizontalRule/index.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<button @click="editor.chain().focus().horizontalRule().run()">
|
||||
horizontalRule
|
||||
</button>
|
||||
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import HorizontalRule from '@tiptap/extension-horizontal-rule'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
HorizontalRule(),
|
||||
],
|
||||
content: `
|
||||
<p>This is a paragraph.</p>
|
||||
<hr>
|
||||
<p>And this is another paragraph.</p>
|
||||
<hr>
|
||||
<p>But between those paragraphs are horizontal rules.</p>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
27
docs/src/demos/Nodes/Image/index.spec.js
Normal file
27
docs/src/demos/Nodes/Image/index.spec.js
Normal file
@@ -0,0 +1,27 @@
|
||||
context('/api/nodes/image', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/nodes/image')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example Text</p>')
|
||||
editor.selectAll()
|
||||
})
|
||||
})
|
||||
|
||||
it('should add an img tag with the correct URL', () => {
|
||||
cy.window().then(win => {
|
||||
cy.stub(win, 'prompt').returns('foobar.png')
|
||||
|
||||
cy.get('.demo__preview button:first')
|
||||
.click()
|
||||
|
||||
cy.window().its('prompt').should('be.called')
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.find('img')
|
||||
.should('have.attr', 'src', 'foobar.png')
|
||||
})
|
||||
})
|
||||
})
|
||||
59
docs/src/demos/Nodes/Image/index.vue
Normal file
59
docs/src/demos/Nodes/Image/index.vue
Normal file
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<button @click="addImage">
|
||||
image
|
||||
</button>
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import Image from '@tiptap/extension-image'
|
||||
import Dropcursor from '@tiptap/extension-dropcursor'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addImage() {
|
||||
const url = window.prompt('URL')
|
||||
|
||||
this.editor.chain().focus().image({ src: url }).run()
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
Image(),
|
||||
Dropcursor(),
|
||||
],
|
||||
content: `
|
||||
<p>This is a basic example of implementing images. Drag to re-order.</p>
|
||||
<img src="https://source.unsplash.com/8xznAGy4HcY/800x400" />
|
||||
<img src="https://source.unsplash.com/K9QHL52rE2k/800x400" />
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
5
docs/src/demos/Nodes/ListItem/index.spec.js
Normal file
5
docs/src/demos/Nodes/ListItem/index.spec.js
Normal file
@@ -0,0 +1,5 @@
|
||||
context('/api/nodes/list-item', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/nodes/list-item')
|
||||
})
|
||||
})
|
||||
73
docs/src/demos/Nodes/ListItem/index.vue
Normal file
73
docs/src/demos/Nodes/ListItem/index.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<button @click="editor.chain().focus().bulletList().run()" :class="{ 'is-active': editor.isActive('bullet_list') }">
|
||||
bullet list
|
||||
</button>
|
||||
<button @click="editor.chain().focus().orderedList().run()" :class="{ 'is-active': editor.isActive('ordered_list') }">
|
||||
ordered list
|
||||
</button>
|
||||
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import BulletList from '@tiptap/extension-bullet-list'
|
||||
import OrderedList from '@tiptap/extension-ordered-list'
|
||||
import ListItem from '@tiptap/extension-list-item'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
BulletList(),
|
||||
OrderedList(),
|
||||
ListItem(),
|
||||
],
|
||||
content: `
|
||||
<p>
|
||||
I like lists. Let’s add one:
|
||||
</p>
|
||||
<ul>
|
||||
<li>This is a bullet list.</li>
|
||||
<li>And it has three list items.</li>
|
||||
<li>Here is the third one.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Do you want to see one more? I bet! Here is another one:
|
||||
</p>
|
||||
<ol>
|
||||
<li>That’s a different list, actually it’s an ordered list.</li>
|
||||
<li>It also has three list items.</li>
|
||||
<li>And all of them are numbered.</li>
|
||||
</ol>
|
||||
<p>
|
||||
Lists would be nothing without list items.
|
||||
</p>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
111
docs/src/demos/Nodes/OrderedList/index.spec.js
Normal file
111
docs/src/demos/Nodes/OrderedList/index.spec.js
Normal file
@@ -0,0 +1,111 @@
|
||||
context('/api/nodes/ordered-list', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/nodes/ordered-list')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example Text</p>')
|
||||
editor.selectAll()
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse ordered lists correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<ol><li><p>Example Text</p></li></ol>')
|
||||
expect(editor.getHTML()).to.eq('<ol><li><p>Example Text</p></li></ol>')
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse ordered lists without paragraphs correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<ol><li>Example Text</li></ol>')
|
||||
expect(editor.getHTML()).to.eq('<ol><li><p>Example Text</p></li></ol>')
|
||||
})
|
||||
})
|
||||
|
||||
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('.demo__preview 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('.demo__preview button:nth-child(1)')
|
||||
.click()
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.find('ol')
|
||||
.should('contain', 'Example Text')
|
||||
|
||||
cy.get('.demo__preview button:nth-child(1)')
|
||||
.click()
|
||||
|
||||
cy.get('.ProseMirror ol')
|
||||
.should('not.exist')
|
||||
})
|
||||
|
||||
it('should leave the list with double enter', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.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.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 remove the ordered list after pressing backspace', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.clearContent()
|
||||
})
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.type('1. {backspace}Example')
|
||||
|
||||
cy.get('.ProseMirror')
|
||||
.find('p')
|
||||
.should('contain', '1. Example')
|
||||
})
|
||||
})
|
||||
58
docs/src/demos/Nodes/OrderedList/index.vue
Normal file
58
docs/src/demos/Nodes/OrderedList/index.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<button @click="editor.chain().focus().orderedList().run()" :class="{ 'is-active': editor.isActive('ordered_list') }">
|
||||
ordered list
|
||||
</button>
|
||||
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import OrderedList from '@tiptap/extension-ordered-list'
|
||||
import ListItem from '@tiptap/extension-list-item'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
OrderedList(),
|
||||
ListItem(),
|
||||
],
|
||||
content: `
|
||||
<ol>
|
||||
<li>A list item</li>
|
||||
<li>And another one</li>
|
||||
</ol>
|
||||
|
||||
<ol start="5">
|
||||
<li>This item starts at 5</li>
|
||||
<li>And another one</li>
|
||||
</ol>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
58
docs/src/demos/Nodes/Paragraph/index.spec.js
Normal file
58
docs/src/demos/Nodes/Paragraph/index.spec.js
Normal file
@@ -0,0 +1,58 @@
|
||||
context('/api/nodes/paragraph', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/nodes/paragraph')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.clearContent()
|
||||
})
|
||||
})
|
||||
|
||||
it('should parse paragraphs correctly', () => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.setContent('<p>Example Text</p>')
|
||||
expect(editor.getHTML()).to.eq('<p>Example Text</p>')
|
||||
|
||||
editor.setContent('<p><x-unknown>Example Text</x-unknown></p>')
|
||||
expect(editor.getHTML()).to.eq('<p>Example Text</p>')
|
||||
|
||||
editor.setContent('<p style="display: block;">Example Text</p>')
|
||||
expect(editor.getHTML()).to.eq('<p>Example Text</p>')
|
||||
})
|
||||
})
|
||||
|
||||
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)
|
||||
})
|
||||
})
|
||||
42
docs/src/demos/Nodes/Paragraph/index.vue
Normal file
42
docs/src/demos/Nodes/Paragraph/index.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
],
|
||||
content: `
|
||||
<p>The Paragraph extension is not required, but it’s very likely you want to use it. It’s needed to write paragraphs of text. 🤓</p>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
70
docs/src/demos/Nodes/Text/TaskList/index.vue
Normal file
70
docs/src/demos/Nodes/Text/TaskList/index.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<button @click="editor.chain().focus().taskList().run()" :class="{ 'is-active': editor.isActive('task_list') }">
|
||||
task list
|
||||
</button>
|
||||
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
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'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
TaskList(),
|
||||
TaskItem(),
|
||||
],
|
||||
content: `
|
||||
<ul data-type="task_list">
|
||||
<li data-type="task_item" data-checked="true">A list item</li>
|
||||
<li data-type="task_item" data-checked="false">And another one</li>
|
||||
</ul>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
ul[data-type="task_list"] {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> input {
|
||||
flex: 0 0 auto;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
18
docs/src/demos/Nodes/Text/index.spec.js
Normal file
18
docs/src/demos/Nodes/Text/index.spec.js
Normal file
@@ -0,0 +1,18 @@
|
||||
context('/api/nodes/text', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/nodes/text')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||
editor.clearContent()
|
||||
})
|
||||
})
|
||||
|
||||
it('text should be wrapped in a paragraph by default', () => {
|
||||
cy.get('.ProseMirror')
|
||||
.type('Example Text')
|
||||
.find('p')
|
||||
.should('contain', 'Example Text')
|
||||
})
|
||||
})
|
||||
42
docs/src/demos/Nodes/Text/index.vue
Normal file
42
docs/src/demos/Nodes/Text/index.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { EditorContent } from '@tiptap/vue'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document(),
|
||||
Paragraph(),
|
||||
Text(),
|
||||
],
|
||||
content: `
|
||||
<p>The Text extension is required, at least if you want to have text in your text editor and that’s very likely.</p>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user