Merge branch 'master' into feature/suggestions

# Conflicts:
#	examples/Components/App/style.scss
#	examples/Components/Subnavigation/index.vue
#	examples/main.js
#	packages/tiptap-extensions/package.json
This commit is contained in:
Philipp Kühn
2018-09-24 15:44:42 +02:00
30 changed files with 567 additions and 162 deletions

View File

@@ -21,6 +21,22 @@
<icon name="italic" />
</button>
<button
class="menubar__button"
:class="{ 'is-active': marks.strike.active() }"
@click="marks.strike.command"
>
<icon name="strike" />
</button>
<button
class="menubar__button"
:class="{ 'is-active': marks.underline.active() }"
@click="marks.underline.command"
>
<icon name="underline" />
</button>
<button
class="menubar__button"
@click="marks.code.command"
@@ -132,6 +148,8 @@ import {
CodeMark,
ItalicMark,
LinkMark,
StrikeMark,
UnderlineMark,
HistoryExtension,
} from 'tiptap-extensions'
@@ -156,6 +174,8 @@ export default {
new CodeMark(),
new ItalicMark(),
new LinkMark(),
new StrikeMark(),
new UnderlineMark(),
new HistoryExtension(),
],
}

View File

@@ -18,49 +18,34 @@
</template>
<script>
import Icon from 'Components/Icon'
import { Editor } from 'tiptap'
import {
BlockquoteNode,
BulletListNode,
CodeBlockHighlightNode,
HardBreakNode,
HeadingNode,
ListItemNode,
OrderedListNode,
TodoItemNode,
TodoListNode,
BoldMark,
CodeMark,
ItalicMark,
LinkMark,
HistoryExtension,
} from 'tiptap-extensions'
import { javascript, css } from './examples'
import {
javascript,
css,
} from './examples'
export default {
components: {
Editor,
Icon,
},
data() {
return {
extensions: [
new BlockquoteNode(),
new BulletListNode(),
new CodeBlockHighlightNode(),
new HardBreakNode(),
new HeadingNode({ maxLevel: 3 }),
new ListItemNode(),
new OrderedListNode(),
new TodoItemNode(),
new TodoListNode(),
new BoldMark(),
new CodeMark(),
new ItalicMark(),
new LinkMark(),
new HistoryExtension(),
],
javascript,
css,

View File

@@ -17,22 +17,12 @@
</template>
<script>
import Icon from 'Components/Icon'
import { Editor } from 'tiptap'
import {
BlockquoteNode,
BulletListNode,
CodeBlockNode,
HardBreakNode,
HeadingNode,
ListItemNode,
OrderedListNode,
TodoItemNode,
TodoListNode,
BoldMark,
CodeMark,
ItalicMark,
LinkMark,
HistoryExtension,
} from 'tiptap-extensions'
import IframeNode from './Iframe.js'
@@ -40,24 +30,14 @@ import IframeNode from './Iframe.js'
export default {
components: {
Editor,
Icon,
},
data() {
return {
extensions: [
new BlockquoteNode(),
new BulletListNode(),
new CodeBlockNode(),
new HardBreakNode(),
new HeadingNode({ maxLevel: 3 }),
new ListItemNode(),
new OrderedListNode(),
new TodoItemNode(),
new TodoListNode(),
new BoldMark(),
new CodeMark(),
new ItalicMark(),
new LinkMark(),
new HistoryExtension(),
// custom extension
new IframeNode(),

View File

@@ -1,6 +1,6 @@
<template>
<div>
<editor class="editor" :extensions="extensions" @update="onUpdate">
<editor class="editor" :extensions="extensions" @update="onUpdate" ref="editor">
<div class="menubar" slot="menubar" slot-scope="{ nodes, marks }">
<div v-if="nodes && marks">
@@ -99,6 +99,15 @@
</editor>
<div class="actions">
<button class="button" @click="clearContent">
Clear Content
</button>
<button class="button" @click="setContent">
Set Content
</button>
</div>
<div class="export">
<h3>JSON</h3>
<pre><code v-html="json"></code></pre>
@@ -161,6 +170,25 @@ export default {
this.json = getJSON()
this.html = getHTML()
},
clearContent() {
this.$refs.editor.clearContent()
this.$refs.editor.focus()
},
setContent() {
this.$refs.editor.setContent({
type: 'doc',
content: [{
type: 'paragraph',
content: [
{
type: 'text',
text: 'This is some inserted text. 👋',
},
],
}],
})
this.$refs.editor.focus()
},
},
}
</script>
@@ -168,10 +196,15 @@ export default {
<style lang="scss" scoped>
@import "~variables";
.actions {
max-width: 30rem;
margin: 0 auto 2rem auto;
}
.export {
max-width: 30rem;
margin: 0 auto 5rem auto;
margin: 0 auto 2rem auto;
pre {
padding: 1rem;

View File

@@ -17,49 +17,29 @@
</template>
<script>
import Icon from 'Components/Icon'
import { Editor } from 'tiptap'
import {
BlockquoteNode,
BulletListNode,
CodeBlockNode,
HardBreakNode,
HeadingNode,
ImageNode,
ListItemNode,
OrderedListNode,
TodoItemNode,
TodoListNode,
BoldMark,
CodeMark,
ItalicMark,
LinkMark,
HistoryExtension,
} from 'tiptap-extensions'
export default {
components: {
Editor,
Icon,
},
data() {
return {
extensions: [
new BlockquoteNode(),
new BulletListNode(),
new CodeBlockNode(),
new HardBreakNode(),
new HeadingNode({ maxLevel: 3 }),
new ImageNode(),
new ListItemNode(),
new OrderedListNode(),
new TodoItemNode(),
new TodoListNode(),
new BoldMark(),
new CodeMark(),
new ItalicMark(),
new LinkMark(),
new HistoryExtension(),
],
}
},

View File

@@ -0,0 +1,44 @@
<template>
<div>
<editor class="editor" :extensions="extensions">
<div class="editor__content" slot="content" slot-scope="props"></div>
</editor>
</div>
</template>
<script>
import { Editor } from 'tiptap'
import {
BulletListNode,
ListItemNode,
PlaceholderExtension,
} from 'tiptap-extensions'
export default {
components: {
Editor,
},
data() {
return {
extensions: [
new BulletListNode(),
new ListItemNode(),
new PlaceholderExtension({
emptyNodeClass: 'is-empty',
}),
],
}
},
}
</script>
<style lang="scss">
.editor p.is-empty:first-child::before {
content: 'Start typing…';
float: left;
color: #aaa;
pointer-events: none;
height: 0;
font-style: italic;
}
</style>

View File

@@ -16,47 +16,29 @@
</template>
<script>
import Icon from 'Components/Icon'
import { Editor } from 'tiptap'
import {
BlockquoteNode,
BulletListNode,
CodeBlockNode,
HardBreakNode,
HeadingNode,
ListItemNode,
OrderedListNode,
TodoItemNode,
TodoListNode,
BoldMark,
CodeMark,
ItalicMark,
LinkMark,
HistoryExtension,
} from 'tiptap-extensions'
export default {
components: {
Editor,
Icon,
},
data() {
return {
extensions: [
new BlockquoteNode(),
new BulletListNode(),
new CodeBlockNode(),
new HardBreakNode(),
new HeadingNode({ maxLevel: 3 }),
new ListItemNode(),
new OrderedListNode(),
new TodoItemNode(),
new TodoListNode(),
new BoldMark(),
new CodeMark(),
new ItalicMark(),
new LinkMark(),
new HistoryExtension(),
],
}
},

View File

@@ -71,20 +71,14 @@
import Icon from 'Components/Icon'
import { Editor } from 'tiptap'
import {
BlockquoteNode,
BulletListNode,
CodeBlockNode,
HardBreakNode,
HeadingNode,
ListItemNode,
OrderedListNode,
TodoItemNode,
TodoListNode,
BoldMark,
CodeMark,
ItalicMark,
LinkMark,
HistoryExtension,
} from 'tiptap-extensions'
export default {
@@ -96,22 +90,60 @@ export default {
return {
customProp: 2,
extensions: [
new BlockquoteNode(),
new BulletListNode(),
new CodeBlockNode(),
new HardBreakNode(),
new HeadingNode({ maxLevel: 3 }),
new ListItemNode(),
new OrderedListNode(),
new TodoItemNode(),
new TodoListNode(),
new BoldMark(),
new CodeMark(),
new ItalicMark(),
new LinkMark(),
new HistoryExtension(),
],
}
},
}
</script>
</script>
<style lang="scss">
@import "~variables";
ul[data-type="todo_list"] {
padding-left: 0;
}
li[data-type="todo_item"] {
display: flex;
flex-direction: row;
}
.todo-checkbox {
border: 2px solid $color-black;
height: 0.9em;
width: 0.9em;
box-sizing: border-box;
margin-right: 10px;
margin-top: 0.3rem;
user-select: none;
-webkit-user-select: none;
cursor: pointer;
border-radius: 0.2em;
background-color: transparent;
transition: 0.4s background;
}
.todo-content {
flex: 1;
}
li[data-done="true"] {
text-decoration: line-through;
}
li[data-done="true"] .todo-checkbox {
background-color: $color-black;
}
li[data-done="false"] {
text-decoration: none;
}
</style>

View File

@@ -33,6 +33,9 @@
<router-link class="subnavigation__link" to="/mentions">
Mentions
</router-link>
<router-link class="subnavigation__link" to="/placeholder">
Placeholder
</router-link>
<router-link class="subnavigation__link" to="/export">
Export HTML or JSON
</router-link>

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>text-strike-through</title><path d="M23.75,12.952A1.25,1.25,0,0,0,22.5,11.7H13.564a.492.492,0,0,1-.282-.09c-.722-.513-1.482-.981-2.218-1.432-2.8-1.715-4.5-2.9-4.5-4.863,0-2.235,2.207-2.569,3.523-2.569a4.54,4.54,0,0,1,3.081.764A2.662,2.662,0,0,1,13.615,5.5l0,.3a1.25,1.25,0,1,0,2.5,0l0-.268A4.887,4.887,0,0,0,14.95,1.755C13.949.741,12.359.248,10.091.248c-3.658,0-6.023,1.989-6.023,5.069,0,2.773,1.892,4.512,4,5.927a.25.25,0,0,1-.139.458H1.5a1.25,1.25,0,0,0,0,2.5H12.477a.251.251,0,0,1,.159.058,4.339,4.339,0,0,1,1.932,3.466c0,3.268-3.426,3.522-4.477,3.522-1.814,0-3.139-.405-3.834-1.173a3.394,3.394,0,0,1-.65-2.7,1.25,1.25,0,0,0-2.488-.246A5.76,5.76,0,0,0,4.4,21.753c1.2,1.324,3.114,2,5.688,2,4.174,0,6.977-2.42,6.977-6.022a6.059,6.059,0,0,0-.849-3.147.25.25,0,0,1,.216-.377H22.5A1.25,1.25,0,0,0,23.75,12.952Z"/></svg>

After

Width:  |  Height:  |  Size: 884 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>text-underline</title><path d="M22.5,21.248H1.5a1.25,1.25,0,0,0,0,2.5h21a1.25,1.25,0,0,0,0-2.5Z"/><path d="M1.978,2.748H3.341a.25.25,0,0,1,.25.25v8.523a8.409,8.409,0,0,0,16.818,0V3a.25.25,0,0,1,.25-.25h1.363a1.25,1.25,0,0,0,0-2.5H16.3a1.25,1.25,0,0,0,0,2.5h1.363a.25.25,0,0,1,.25.25v8.523a5.909,5.909,0,0,1-11.818,0V3a.25.25,0,0,1,.25-.25H7.7a1.25,1.25,0,1,0,0-2.5H1.978a1.25,1.25,0,0,0,0,2.5Z"/></svg>

After

Width:  |  Height:  |  Size: 469 B

View File

@@ -0,0 +1,56 @@
.editor {
position: relative;
max-width: 30rem;
margin: 0 auto 5rem auto;
&__content {
pre {
padding: 0.7rem 1rem;
border-radius: 5px;
background: $color-black;
color: $color-white;
font-size: 0.8rem;
overflow-x: auto;
code {
display: block;
}
}
p code {
display: inline-block;
padding: 0 0.4rem;
border-radius: 5px;
font-size: 0.8rem;
font-weight: bold;
background: rgba($color-black, 0.1);
color: rgba($color-black, 0.8);
}
ul,
ol {
padding-left: 1rem;
}
a {
color: inherit;
}
blockquote {
border-left: 3px solid rgba($color-black, 0.1);
color: rgba($color-black, 0.8);
padding-left: 0.8rem;
font-style: italic;
p {
margin: 0;
}
}
img {
max-width: 100%;
border-radius: 3px;
}
}
}

View File

@@ -59,4 +59,21 @@ h1,
h2,
h3 {
line-height: 1.3;
}
}
.button {
font-weight: bold;
display: inline-flex;
background: transparent;
border: 0;
color: $color-black;
padding: 0.2rem 0.5rem;
margin-right: 0.2rem;
border-radius: 3px;
cursor: pointer;
background-color: rgba($color-black, 0.1);
}
@import "./editor";
@import "./menubar";
@import "./menububble";

View File

@@ -0,0 +1,37 @@
.menubar {
display: flex;
margin-bottom: 1rem;
transition: visibility 0.2s 0.4s, opacity 0.2s 0.4s;
&.is-hidden {
visibility: hidden;
opacity: 0;
}
&.is-focused {
visibility: visible;
opacity: 1;
transition: visibility 0.2s, opacity 0.2s;
}
&__button {
font-weight: bold;
display: inline-flex;
background: transparent;
border: 0;
color: $color-black;
padding: 0.2rem 0.5rem;
margin-right: 0.2rem;
border-radius: 3px;
cursor: pointer;
&:hover {
background-color: rgba($color-black, 0.05);
}
&.is-active {
background-color: rgba($color-black, 0.1);
}
}
}

View File

@@ -0,0 +1,48 @@
.menububble {
position: absolute;
display: flex;
z-index: 20;
background: $color-black;
border-radius: 5px;
padding: 0.3rem;
margin-bottom: 0.5rem;
transform: translateX(-50%);
visibility: hidden;
opacity: 0;
transition: opacity 0.2s, visibility 0.2s;
&__button {
display: inline-flex;
background: transparent;
border: 0;
color: $color-white;
padding: 0.2rem 0.5rem;
margin-right: 0.2rem;
border-radius: 3px;
cursor: pointer;
&:last-child {
margin-right: 0;
}
&:hover {
background-color: rgba($color-white, 0.1);
}
&.is-active {
background-color: rgba($color-white, 0.2);
}
}
&__form {
display: flex;
align-items: center;
}
&__input {
font: inherit;
border: none;
background: transparent;
color: $color-white;
}
}

View File

@@ -3,18 +3,6 @@ import Vue from 'vue'
import VueRouter from 'vue-router'
import svgSpriteLoader from 'helpers/svg-sprite-loader'
import App from 'Components/App'
import RouteBasic from 'Components/Routes/Basic'
import RouteMenuBubble from 'Components/Routes/MenuBubble'
import RouteLinks from 'Components/Routes/Links'
import RouteImages from 'Components/Routes/Images'
import RouteHidingMenuBar from 'Components/Routes/HidingMenuBar'
import RouteTodoList from 'Components/Routes/TodoList'
import RouteMarkdownShortcuts from 'Components/Routes/MarkdownShortcuts'
import RouteCodeHighlighting from 'Components/Routes/CodeHighlighting'
import RouteReadOnly from 'Components/Routes/ReadOnly'
import RouteEmbeds from 'Components/Routes/Embeds'
import RouteMentions from 'Components/Routes/Mentions'
import RouteExport from 'Components/Routes/Export'
const __svg__ = { path: './assets/images/icons/*.svg', name: 'assets/images/[hash].sprite.svg' }
svgSpriteLoader(__svg__.filename)
@@ -26,84 +14,91 @@ Vue.use(VueRouter)
const routes = [
{
path: '/',
component: RouteBasic,
component: () => import('Components/Routes/Basic'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/Basic',
},
},
{
path: '/menu-bubble',
component: RouteMenuBubble,
component: () => import('Components/Routes/MenuBubble'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/MenuBubble',
},
},
{
path: '/links',
component: RouteLinks,
component: () => import('Components/Routes/Links'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/Links',
},
},
{
path: '/images',
component: RouteImages,
component: () => import('Components/Routes/Images'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/Images',
},
},
{
path: '/hiding-menu-bar',
component: RouteHidingMenuBar,
component: () => import('Components/Routes/HidingMenuBar'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/HidingMenuBar',
},
},
{
path: '/todo-list',
component: RouteTodoList,
component: () => import('Components/Routes/TodoList'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/TodoList',
},
},
{
path: '/markdown-shortcuts',
component: RouteMarkdownShortcuts,
component: () => import('Components/Routes/MarkdownShortcuts'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/MarkdownShortcuts',
},
},
{
path: '/code-highlighting',
component: RouteCodeHighlighting,
component: () => import('Components/Routes/CodeHighlighting'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/CodeHighlighting',
},
},
{
path: '/read-only',
component: RouteReadOnly,
component: () => import('Components/Routes/ReadOnly'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/ReadOnly',
},
},
{
path: '/embeds',
component: RouteEmbeds,
component: () => import('Components/Routes/Embeds'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/Embeds',
},
},
{
path: '/mentions',
component: RouteMentions,
component: () => import('Components/Routes/Mentions'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/Mentions',
},
},
{
path: '/placeholder',
component: () => import('Components/Routes/Placeholder'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/Placeholder',
},
},
{
path: '/export',
component: RouteExport,
component: () => import('Components/Routes/Export'),
meta: {
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/Export',
},