remove tiptap, start simple homegrown richtext functionalities

* menu now sends command events and button states
* menu state is synced with the elements at caret postion
* menu functionalities are not yet implemented
master
koehr 5 years ago committed by Norman
parent a33363eef0
commit c64b9a95fb

@ -10,8 +10,6 @@
"dependencies": {
"core-js": "^3.6.4",
"register-service-worker": "^1.6.2",
"tiptap": "^1.26.6",
"tiptap-extensions": "^1.28.6",
"vue": "^2.6.11",
"vue-router": "^3.1.5"
},
@ -36,9 +34,6 @@
"vue-property-decorator": "^8.4.0",
"vue-template-compiler": "^2.6.11"
},
"resolutions": {
"prosemirror-model": "1.8.2"
},
"eslintConfig": {
"root": true,
"env": {
@ -51,9 +46,6 @@
],
"parserOptions": {
"ecmaVersion": 2020
},
"rules": {
"no-useless-constructor": "off"
}
},
"browserslist": [

@ -1,49 +1,43 @@
<template>
<editor-menu-bar :editor="editor" v-slot="{ commands, isActive, focused }">
<div class="menu-bar" :class="{ active: focused }">
<button class="editor-button-bold" :class="{ active: active.bold }" @click="menuAction('bold', commands.bold, isActive)" />
<button class="editor-button-italic" :class="{ active: active.italic }" @click="menuAction('italic', commands.italic, isActive)" />
<div class="menu-bar" :class="{ active }">
<button class="editor-button-bold" :class="{ active: value.bold }" @click="menuAction('bold')" />
<button class="editor-button-italic" :class="{ active: value.italic }" @click="menuAction('italic')" />
<button class="editor-button-paragraph" :class="{ active: active.paragraph }" @click="menuAction('paragraph', commands.paragraph, isActive)" />
<button class="editor-button-heading2" :class="{ active: active.heading2 }" @click="menuAction('heading2', commands.heading({ level: 2}), isActive)" />
<button class="editor-button-heading3" :class="{ active: active.heading3 }" @click="menuAction('heading3', commands.heading({ level: 3}), isActive)" />
<button class="editor-button-paragraph" :class="{ active: value.paragraph }" @click="menuAction('paragraph')" />
<button class="editor-button-heading2" :class="{ active: value.heading2 }" @click="menuAction('heading2')" />
<button class="editor-button-heading3" :class="{ active: value.heading3 }" @click="menuAction('heading3')" />
<button class="editor-button-bullet-list" :class="{ active: active.bullet_list }" @click="menuAction('bullet_list', commands.bullet_list, isActive)" />
<button class="editor-button-horizontal-rule" :class="{ active: active.horizontal_rule }" @click="menuAction('horizontal_rule', commands.horizontal_rule, isActive)" />
<button class="editor-button-bullet-list" :class="{ active: value.bulletList }" @click="menuAction('bulletList')" />
<button class="editor-button-horizontal-rule" :class="{ active: value.separator}" @click="menuAction('separator')" />
<button class="editor-button-horizontal-rule" :class="{ active: value.spacer}" @click="menuAction('spacer')" />
<button class="editor-button-stat-block" :class="{ active: active.stat_block }" @click="menuAction('stat_block', commands.stat_block, isActive)" />
<button class="editor-button-stat-block" :class="{ active: value.statBlock }" @click="menuAction('statBlock')" />
</div>
</editor-menu-bar>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import { Editor, EditorMenuBar } from 'tiptap'
import { blocks, State } from '@/editor.ts'
@Component({
components: { EditorMenuBar }
})
@Component
export default class DeckCardEditorMenu extends Vue {
@Prop() public readonly editor!: Editor
@Prop() public readonly active!: boolean
@Prop() public readonly value!: State
private active: {[key: string]: boolean} = {
bold: false,
italic: false,
private menuAction (name: string) {
const newState = { ...this.value }
paragraph: false,
heading2: false,
heading3: false,
bulletList: false,
horizontalLule: false
if (blocks.indexOf(name) >= 0) { // blocks behave like radio buttons
blocks.forEach(block => {
newState[block] = false
})
newState[name] = true
} else { // marks behave like checkboxes
newState[name] = !newState[name]
}
private menuAction (name: string, command: () => void, isActive: {[key: string]: () => boolean}) {
command()
Object.keys(this.active).forEach(action => {
this.active[action] = isActive[action]()
})
this.$emit('input', newState)
this.$emit('action', name)
}
}
</script>

@ -0,0 +1,184 @@
<template>
<main>
<deck-card-editor-menu
:active="contentInFocus"
@action="editorAction"
v-model="menuState"
/>
<div
:ref="content"
class="card-content"
:contenteditable="active"
@focus="start"
@click="syncMenuStateIfFocussed"
@keyup="syncMenuStateOnKeyPress"
@blur="stop"
>
<h2>card content</h2>
<hr />
<p><b>foo:</b> boom</p>
<p><b>bar:</b> blam</p>
<hr />
<p>Some description maybe?</p>
</div>
</main>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import DeckCardEditorMenu from '@/components/deck-card-editor-menu.vue'
import {
elementNameToMenuState,
getElementAndParentName,
marks,
blocks,
State,
movementKeys,
controlSequenceKeys
} from '@/editor.ts'
@Component({
components: { DeckCardEditorMenu }
})
export default class DeckCardEditor extends Vue {
@Prop() public readonly active!: boolean
@Prop() public readonly content!: Card['content']
private contentInFocus = false
private menuState: State = {
bold: false,
italic: false,
paragraph: true,
heading1: false,
heading2: false,
heading3: false,
bulletList: false,
spacer: false,
separator: false,
statBlock: false
}
private clearMarks () {
marks.forEach(mark => {
this.menuState[mark] = false
})
}
private toggleBlock (name: string) {
blocks.forEach(block => {
this.menuState[block] = false
})
this.menuState[name] = true
}
private setMenuState (elementName: string, parentName?: string) {
const stateName = elementNameToMenuState[elementName]
// marks are always inside a block element
if (marks.indexOf(stateName) >= 0 && parentName) {
const parentStateName = elementNameToMenuState[parentName]
// marks are inclusive like checkboxes
this.menuState[stateName] = true
// but blocks are exclusive like radio buttons
this.toggleBlock(parentStateName)
} else {
this.clearMarks()
this.toggleBlock(stateName)
}
}
private editorAction (action: string) {
console.log('action', action)
// const content = this.$refs.content
}
private syncMenuState () {
const sel = window.getSelection()?.focusNode
if (!sel) return
const [elementName, parentName] = getElementAndParentName(sel)
console.log('focussed element', elementName, parentName)
if (!elementName) return
this.setMenuState(elementName, parentName)
}
private syncMenuStateIfFocussed () {
if (this.contentInFocus) this.syncMenuState()
}
private syncMenuStateOnKeyPress (event: KeyboardEvent) {
// undo/redo/cut/paste
const isCtrlSq = event.ctrlKey && controlSequenceKeys.indexOf(event.key) >= 0
// arrow keys, enter, delete, etc
const isMove = movementKeys.indexOf(event.key) >= 0
if (isCtrlSq || isMove) this.syncMenuState()
}
private start () {
this.contentInFocus = true
this.syncMenuState()
}
private stop () {
this.contentInFocus = false
}
}
</script>
<style scoped>
.card-content p {
margin: 0;
line-height: 1.2;
}
.card-content ul {
list-style-position: inside;
margin: 0;
padding-left: .5em;
}
.card-content li > p {
display: inline;
}
.card-content h2 {
font-size: 1.4rem;
color: var(--highlight-color);
margin: 0;
font-weight: normal;
}
.card-content h3 {
font-size: 1.4rem;
color: var(--highlight-color);
margin: 0 0 .2em 0;
font-weight: normal;
font-variant: small-caps;
line-height: .9em;
border-bottom: 1px solid var(--highlight-color);
}
.card-content hr {
height: 0;
margin: .2em 0;
border: 2px solid var(--highlight-color);
}
.card-content hr.pointing-right {
height: 0;
margin: .2em 0;
border-style: solid;
border-width: 2px 0 2px 220px;
border-color: transparent transparent transparent var(--highlight-color);
}
.card-content hr.pointing-left {
height: 0;
margin: .2em 0;
border-style: solid;
border-width: 2px 220px 2px 0;
border-color: transparent var(--highlight-color) transparent transparent;
}
[contenteditable="true"] { outline: none; }
</style>

@ -10,15 +10,13 @@
<section name="card-front" class="card-front">
<header>
<h1 :contenteditable="isSelection"
@blur="editField('name', $event)"
@keypress.enter.prevent="editField('name', $event)">
{{ card.name }}
</h1>
<img :src="icon" />
</header>
<main>
<deck-card-editor-menu :editor="editor" />
<editor-content :editor="editor" />
</main>
<deck-card-editor :active="isSelection" :content="card.content" @input="$emit('edit', $event)" />
</section>
<section name="card-back" class="card-back">
<div class="icon-wrapper">
@ -33,65 +31,18 @@
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import { cardWHtoStyle, iconPath } from '@/lib'
import { Editor, EditorContent } from 'tiptap'
import {
Heading,
Bold,
Italic,
HorizontalRule,
BulletList,
ListItem,
History,
Table,
TableCell,
TableRow,
TableHeader
} from 'tiptap-extensions'
import StatBlock from '@/editor/stat-block.js'
import DeckCardEditorMenu from '@/components/deck-card-editor-menu.vue'
interface EditorContext {
state: object;
getHTML: () => string;
getJSON: () => ContentNode;
transaction: object;
}
const extensions = [
new Heading({ level: [2, 3] }),
new Bold(),
new Italic(),
new HorizontalRule(),
new BulletList(),
new ListItem(),
new History(),
new StatBlock()
]
import DeckCardEditor from '@/components/deck-card-editor.vue'
@Component({
components: { EditorContent, DeckCardEditorMenu }
components: { DeckCardEditor }
})
export default class DeckCard extends Vue {
@Prop() public readonly card!: Card
@Prop() public readonly deck!: Deck
@Prop() public readonly isSelection!: boolean
private editor = new Editor({ autoFocus: false, extensions })
private mounted () {
this.editor.on('update', ({ getJSON }: EditorContext) => {
const doc = getJSON()
this.$emit('edit', { field: 'content', value: doc.content })
})
this.editor.setContent({
type: 'doc',
content: this.card.content
})
}
private beforeDestroy () {
this.editor.destroy()
}
/// TODO: onEdit
// this.$emit('edit', { field: 'content', value: doc.content })
private editHeadline = false;
private editFieldIndex: number | null = null;
@ -276,57 +227,3 @@ export default class DeckCard extends Vue {
}
}
</style>
<style>
.ProseMirror p {
margin: 0;
line-height: 1.2;
}
.ProseMirror ul {
list-style-position: inside;
margin: 0;
padding-left: .5em;
}
.ProseMirror li > p {
display: inline;
}
.ProseMirror h2 {
font-size: 1.4rem;
color: var(--highlight-color);
margin: 0;
font-weight: normal;
}
.ProseMirror h3 {
font-size: 1.4rem;
color: var(--highlight-color);
margin: 0 0 .2em 0;
font-weight: normal;
font-variant: small-caps;
line-height: .9em;
border-bottom: 1px solid var(--highlight-color);
}
.ProseMirror hr {
height: 0;
margin: .2em 0;
border: 2px solid var(--highlight-color);
}
.ProseMirror hr.pointing-right {
height: 0;
margin: .2em 0;
border-style: solid;
border-width: 2px 0 2px 220px;
border-color: transparent transparent transparent var(--highlight-color);
}
.ProseMirror hr.pointing-left {
height: 0;
margin: .2em 0;
border-style: solid;
border-width: 2px 220px 2px 0;
border-color: transparent var(--highlight-color) transparent transparent;
}
[contenteditable="true"] { outline: none; }
</style>

@ -0,0 +1,47 @@
export type State = KV<boolean>
export const movementKeys = [
'ArrowLeft',
'ArrowRight',
'ArrowUp',
'ArrowDown',
'Delete',
'Backspace',
'Enter'
]
export const controlSequenceKeys = ['p', 'x', 'y', 'z', 'Z']
export const elementNameToMenuState: KV<string> = {
B: 'bold',
STRONG: 'bold',
I: 'italic',
EM: 'italic',
P: 'paragraph',
H1: 'heading1',
H2: 'heading2',
H3: 'heading3',
UL: 'bulletList',
OL: 'numberedList',
HR: 'separator'
}
export const marks = ['bold', 'italic']
export const blocks = [
'paragraph',
'heading1',
'heading2',
'heading3',
'bulletList',
'spacer',
'separator',
'statBlock'
]
export function getElementAndParentName (el: Node) {
const element = el.nodeName === '#text' ? el.parentElement : el
return [
element?.nodeName,
element?.parentElement?.nodeName
]
}

@ -1,53 +0,0 @@
import { Node } from 'tiptap'
import { tableNodes, tableEditing, goToNextCell, deleteTable } from 'prosemirror-tables'
import { createTable } from 'prosemirror-utils'
import { TextSelection } from 'prosemirror-state'
export default class StatBlock extends Node {
get name () {
return 'stat_block'
}
get defaultOptions () {
return {
resizable: false
}
}
get schema () {
return {
group: 'block',
content: 'stat_column+',
toDOM: () => ['ol', { 'data-type': this.name }, 0],
parseDOM: [{
priority: 51,
tag: `[data-type="${this.name}"]`
}]
}
}
commands ({ schema }) {
return () => (state, dispatch) => {
const offset = state.tr.selection.anchor + 1
const nodes = createTable(schema, 2, 6, true)
const tr = state.tr.replaceSelectionWith(nodes).scrollIntoView()
const resolvedPos = tr.doc.resolve(offset)
tr.setSelection(TextSelection.near(resolvedPos))
dispatch(tr)
}
}
keys () {
return {
Tab: goToNextCell(1),
'Shift-Tab': goToNextCell(-1)
}
}
get plugins () {
return [tableEditing()]
}
}

@ -1,49 +0,0 @@
import { Node } from 'tiptap'
import { tableEditing, goToNextCell, deleteTable } from 'prosemirror-tables'
import { createTable } from 'prosemirror-utils'
import { TextSelection } from 'prosemirror-state'
import { TableNodes } from 'tiptap-extensions'
export default class StatBlock extends Node {
public get name () {
return 'stat_block'
}
public get defaultOptions () {
return {
resizable: false
}
}
public get schema () {
return TableNodes.table
}
public commands ({ schema }) {
return {
createStatBlock: () => (state, dispatch) => {
const offset = state.tr.selection.anchor + 1
const nodes = createTable(schema, 2, 6, true)
const tr = state.tr.replaceSelectionWith(nodes).scrollIntoView()
const resolvedPos = tr.doc.resolve(offset)
tr.setSelection(TextSelection.near(resolvedPos))
dispatch(tr)
},
deleteTable: () => deleteTable
}
}
public keys () {
return {
Tab: goToNextCell(1),
'Shift-Tab': goToNextCell(-1)
}
}
public get plugins () {
return [tableEditing()]
}
}

@ -41,7 +41,7 @@ export function defaultDeck (): Deck {
export function defaultCard (): Card {
return {
id: `c${randomId()}`,
name: '',
name: 'no title yet',
count: 1,
tags: [],
icon: 'robe',

@ -1,104 +0,0 @@
/* eslint @typescript-eslint/no-explicit-any: 0 */
declare module 'tiptap-extensions' {
import { Node, Mark, Extension } from 'tiptap'
export class Heading extends Node {
[key: string]: any
}
export class Blockquote extends Node {
[key: string]: any
}
export class BulletList extends Node {
[key: string]: any
}
export class Code extends Node {
[key: string]: any
}
export class CodeBlock extends Node {
[key: string]: any
}
export class CodeBlockHighlight extends Node {
[key: string]: any
}
export class HardBreak extends Node {
[key: string]: any
}
export class HorizontalRule extends Node {
[key: string]: any
}
export class Image extends Node {
[key: string]: any
}
export class ListItem extends Node {
[key: string]: any
}
export class Mention extends Node {
[key: string]: any
}
export class OrderedList extends Node {
[key: string]: any
}
export class Table extends Node {
[key: string]: any
}
export class TableCell extends Node {
[key: string]: any
}
export class TableHeader extends Node {
[key: string]: any
}
export class TableNodes extends Node {
[key: string]: any
}
export class TableRow extends Node {
[key: string]: any
}
export class TodoItem extends Node {
[key: string]: any
}
export class TodoList extends Node {
[key: string]: any
}
export class Link extends Mark {
[key: string]: any
}
export class Bold extends Mark {
[key: string]: any
}
export class Italic extends Mark {
[key: string]: any
}
export class Strike extends Mark {
[key: string]: any
}
export class Underline extends Mark {
[key: string]: any
}
export class Collaboration extends Extension {
[key: string]: any
}
export class Focus extends Extension {
[key: string]: any
}
export class History extends Extension {
[key: string]: any
}
export class Placeholder extends Extension {
[key: string]: any
}
export class Search extends Extension {
[key: string]: any
}
export class TrailingNode extends Extension {
[key: string]: any
}
export class Suggestions {
[key: string]: any
}
export class Highlight {
[key: string]: any
}
}

@ -1,56 +0,0 @@
/* eslint @typescript-eslint/no-explicit-any: 0 */
declare module 'tiptap' {
import { Vue } from 'vue/types/vue'
export class Emitter {
on(event: any, fn: (...args: any[]) => void): Emitter
emit(event: any, ...args: any[]): Emitter
off(event: any, fn: (...args: any[]) => void): Emitter
}
export class Editor extends Emitter {
constructor (...arg: any[])
[key: string]: any
}
export class Extension {
constructor(...arg: any[])
init(): null
bindEditor(editor: Editor): void
get name(): string|null
get type(): string
get update(): object
get defaultOptions(): object
get plugins(): any[]
inputRules(): any[]
pasteRules(): any[]
keys(): object
}
export class Node extends Extension {
get type(): 'node'
get view(): null
get schema(): null
command(): () => object
}
export class Mark extends Extension {
get type(): 'mark'
get view(): null
get schema(): null
command(): () => object
}
export class EditorMenuBubble extends Vue {
[key: string]: any
}
export class EditorContent extends Vue {
[key: string]: any
}
export class EditorMenuBar extends Vue {
[key: string]: any
}
export class EditorFloatingMenu extends Vue {
[key: string]: any
}
}

4
src/shims.d.ts vendored

@ -1,3 +1,7 @@
interface KV<V> {
[key: string]: V;
}
interface TextNode {
type: 'text';
text: string;

@ -86,7 +86,6 @@ export default class DeckView extends Vue {
if (this.deck === null) return
const newCard = defaultCard()
newCard.name = 'Click here to add an awesome title'
newCard.content = [{
type: 'heading',
attrs: { level: 2 },

@ -3797,13 +3797,6 @@ fastq@^1.6.0:
dependencies:
reusify "^1.0.4"
fault@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13"
integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==
dependencies:
format "^0.2.0"
faye-websocket@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
@ -4024,11 +4017,6 @@ form-data@~2.3.2:
combined-stream "^1.0.6"
mime-types "^2.1.12"
format@^0.2.0:
version "0.2.2"
resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b"
integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=
forwarded@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
@ -4390,11 +4378,6 @@ highlight.js@^9.6.0:
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.1.tgz#ed21aa001fe6252bb10a3d76d47573c6539fe13c"
integrity sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg==
highlight.js@~9.16.0:
version "9.16.2"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.16.2.tgz#68368d039ffe1c6211bcc07e483daf95de3e403e"
integrity sha512-feMUrVLZvjy0oC7FVJQcSQRqbBq9kwqnYE4+Kj9ZjbHh3g+BisiPgF49NyQbVLNdrL/qqZr3Ca9yOKwgn2i/tw==
hmac-drbg@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@ -5541,14 +5524,6 @@ lower-case@^1.1.1:
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
lowlight@1.13.0:
version "1.13.0"
resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.13.0.tgz#9b4fd00559985e40e11c916ccab14c7c0cf4320d"
integrity sha512-bFXLa+UO1eM3zieFAcNqf6rTQ1D5ERFv64/euQbbH/LT3U9XXwH6tOrgUAGWDsQ1QgN3ZhgOcv8p3/S+qKGdTQ==
dependencies:
fault "^1.0.2"
highlight.js "~9.16.0"
lru-cache@^4.0.1, lru-cache@^4.1.2:
version "4.1.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
@ -7029,137 +7004,13 @@ promise-inflight@^1.0.1:
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
prosemirror-collab@1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/prosemirror-collab/-/prosemirror-collab-1.2.2.tgz#8d2c0e82779cfef5d051154bd0836428bd6d9c4a"
integrity sha512-tBnHKMLgy5Qmx9MYVcLfs3pAyjtcqYYDd9kp3y+LSiQzkhMQDfZSV3NXWe4Gsly32adSef173BvObwfoSQL5MA==
dependencies:
prosemirror-state "^1.0.0"
prosemirror-commands@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.1.2.tgz#6868cabc9f9112fba94c805139473527774b0dea"
integrity sha512-JBa06kjgX67d9JVUVJbCkxwvSGtQnWAN/85nq9csOMS5Z9WZLEvVDtVvZranNlu8l/XNVBWrZxOOK+pB03eTfA==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-state "^1.0.0"
prosemirror-transform "^1.0.0"
prosemirror-dropcursor@1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.3.2.tgz#28738c4ed7102e814d7a8a26d70018523fc7cd6d"
integrity sha512-4c94OUGyobGnwcQI70OXyMhE/9T4aTgjU+CHxkd5c7D+jH/J0mKM/lk+jneFVKt7+E4/M0D9HzRPifu8U28Thw==
dependencies:
prosemirror-state "^1.0.0"
prosemirror-transform "^1.1.0"
prosemirror-view "^1.1.0"
prosemirror-gapcursor@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.1.2.tgz#a1400a86a51d4cccc065e68d5625a9fb5bc623e0"
integrity sha512-Z+eqk6RysZVxidGWN5aWoSTbn5bTHf1XZ+nQJVwUSdwdBVkfQMFdTHgfrXA8W5MhHHdNg/EEEYG3z3Zi/vE2QQ==
dependencies:
prosemirror-keymap "^1.0.0"
prosemirror-model "^1.0.0"
prosemirror-state "^1.0.0"
prosemirror-view "^1.0.0"
prosemirror-history@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prosemirror-history/-/prosemirror-history-1.1.2.tgz#3e8f11efbd316e98322028be67549df1f94fc6da"
integrity sha512-erhxYS5gm/6MiXP8jUoJBgc8IbaqjHDVPl9KGg5JrMZOSSOwHv85+4Fb0Q7sYtv2fYwAjOSw/kSA9vkxJ6wOwA==
dependencies:
prosemirror-state "^1.2.2"
prosemirror-transform "^1.0.0"
rope-sequence "^1.3.0"
prosemirror-inputrules@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prosemirror-inputrules/-/prosemirror-inputrules-1.1.2.tgz#487e46c763e1212a4577397aba7706139084f012"
integrity sha512-Ja5Z3BWestlHYGvtSGqyvxMeB8QEuBjlHM8YnKtLGUXMDp965qdDV4goV8lJb17kIWHk7e7JNj6Catuoa3302g==
dependencies:
prosemirror-state "^1.0.0"
prosemirror-transform "^1.0.0"
prosemirror-keymap@1.1.3, prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.2:
version "1.1.3"
resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.1.3.tgz#be22d6108df2521608e9216a87b1a810f0ed361e"
integrity sha512-PRA4NzkUMzV/NFf5pyQ6tmlIHiW/qjQ1kGWUlV2rF/dvlOxtpGpTEjIMhWgLuMf+HiDEFnUEP7uhYXu+t+491g==
dependencies:
prosemirror-state "^1.0.0"
w3c-keyname "^2.2.0"
prosemirror-model@1.8.2, prosemirror-model@^1.0.0, prosemirror-model@^1.1.0, prosemirror-model@^1.8.1:
prosemirror-model@1.8.2:
version "1.8.2"
resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.8.2.tgz#c74eaacb0bbfea49b59a6d89fef5516181666a56"
integrity sha512-piffokzW7opZVCjf/9YaoXvTC0g7zMRWKJib1hpphPfC+4x6ZXe5CiExgycoWZJe59VxxP7uHX8aFiwg2i9mUQ==
dependencies:
orderedmap "^1.1.0"
prosemirror-schema-list@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prosemirror-schema-list/-/prosemirror-schema-list-1.1.2.tgz#310809209094b03425da7f5c337105074913da6c"
integrity sha512-dgM9PwtM4twa5WsgSYMB+J8bwjnR43DAD3L9MsR9rKm/nZR5Y85xcjB7gusVMSsbQ2NomMZF03RE6No6mTnclQ==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-transform "^1.0.0"
prosemirror-state@1.3.2, prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/prosemirror-state/-/prosemirror-state-1.3.2.tgz#1b910b0dc01c1f00926bb9ba1589f7b7ac0d658b"
integrity sha512-t/JqE3aR0SV9QrzFVkAXsQwsgrQBNs/BDbcFH20RssW0xauqNNdjTXxy/J/kM7F+0zYi6+BRmz7cMMQQFU3mwQ==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-transform "^1.0.0"
prosemirror-tables@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/prosemirror-tables/-/prosemirror-tables-1.0.0.tgz#ec3d0b11e638c6a92dd14ae816d0a2efd1719b70"
integrity sha512-zFw5Us4G5Vdq0yIj8GiqZOGA6ud5UKpMKElux9O0HrfmhkuGa1jf1PCpz2R5pmIQJv+tIM24H1mox/ODBAX37Q==
dependencies:
prosemirror-keymap "^1.1.2"
prosemirror-model "^1.8.1"
prosemirror-state "^1.3.1"
prosemirror-transform "^1.2.1"
prosemirror-view "^1.13.3"
prosemirror-transform@1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.2.2.tgz#4439ae7e88ea1395d9beed6a4cd852d72b16ed2f"
integrity sha512-expO11jAsxaHk2RdZtzPsumc1bAAZi4UiXwTLQbftsdnIUWZE5Snyag595p1lx/B8QHUZ6tYWWOaOkzXKoJmYw==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.2.4.tgz#8d5843834f5ccedfb614faa9220672bb4834b00a"
integrity sha512-0A668uf0EN89L9O9brE05kHcqp7FHmT5YN7Tom58Kj926QqOBs7iNRHDLWxrSaQB5MNZtzDOD9T3EyJ88YDcBg==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-utils@0.9.6:
version "0.9.6"
resolved "https://registry.yarnpkg.com/prosemirror-utils/-/prosemirror-utils-0.9.6.tgz#3d97bd85897e3b535555867dc95a51399116a973"
integrity sha512-UC+j9hQQ1POYfMc5p7UFxBTptRiGPR7Kkmbl3jVvU8VgQbkI89tR/GK+3QYC8n+VvBZrtAoCrJItNhWSxX3slA==
prosemirror-view@1.13.4:
version "1.13.4"
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.13.4.tgz#01d873db7731e0aacc410a9038447d1b7536fd07"
integrity sha512-mtgWEK16uYQFk3kijRlkSpAmDuy7rxYuv0pgyEBDmLT1PCPY8380CoaYnP8znUT6BXIGlJ8oTveK3M50U+B0vw==
dependencies:
prosemirror-model "^1.1.0"
prosemirror-state "^1.0.0"
prosemirror-transform "^1.1.0"
prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3:
version "1.14.4"
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.14.4.tgz#dccfdc6fc5d0206d0b0b7a6abb688d3f741406d6"
integrity sha512-qPlKWigymKio7Ed52E+mwZEn2TJE28u8Masj0ygGHYZRhY/abB/s0XEGLwx2FTsvt92gIqfRRezhUzTk3eE2rQ==
dependencies:
prosemirror-model "^1.1.0"
prosemirror-state "^1.0.0"
prosemirror-transform "^1.1.0"
proxy-addr@~2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
@ -7638,11 +7489,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0"
inherits "^2.0.1"
rope-sequence@^1.3.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.3.2.tgz#a19e02d72991ca71feb6b5f8a91154e48e3c098b"
integrity sha512-ku6MFrwEVSVmXLvy3dYph3LAMNS0890K7fabn+0YIRQ2T96T9F4gkFf0vf0WW0JUraNWwGRtInEpH7yO4tbQZg==
run-async@^2.2.0, run-async@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8"
@ -8473,63 +8319,6 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tiptap-commands@^1.12.5:
version "1.12.5"
resolved "https://registry.yarnpkg.com/tiptap-commands/-/tiptap-commands-1.12.5.tgz#d2bd1adcc79fe47938bd64b91b6dec4688a88086"
integrity sha512-wzQCH3CL1VWy6E47Hy+9kt882w7SND+FD9e9xAAsYhG/QI0cmuvAf/8doZZhUmYwkraYeF7/2bU04IXr36t44Q==
dependencies:
prosemirror-commands "1.1.2"
prosemirror-inputrules "1.1.2"
prosemirror-model "1.8.2"
prosemirror-schema-list "1.1.2"
prosemirror-state "1.3.2"
prosemirror-tables "1.0.0"
prosemirror-utils "0.9.6"
tiptap-utils "^1.8.3"
tiptap-extensions@^1.28.6:
version "1.28.6"
resolved "https://registry.yarnpkg.com/tiptap-extensions/-/tiptap-extensions-1.28.6.tgz#ce3ca3ccd9c9658e749c5aa5e97255a70468eaff"
integrity sha512-hkYKJHxkqmeIRyuOaVvsrC/IcoXZmBw/Gx4JJHPiCAKvLQyjgYZpNjbVH9nIgdlxLvVjFDVBoPWGHy00qGp8qQ==
dependencies:
lowlight "1.13.0"
prosemirror-collab "1.2.2"
prosemirror-history "1.1.2"
prosemirror-model "1.8.2"
prosemirror-state "1.3.2"
prosemirror-tables "1.0.0"
prosemirror-transform "1.2.2"
prosemirror-utils "0.9.6"
prosemirror-view "1.13.4"
tiptap "^1.26.6"
tiptap-commands "^1.12.5"
tiptap-utils@^1.8.3:
version "1.8.3"
resolved "https://registry.yarnpkg.com/tiptap-utils/-/tiptap-utils-1.8.3.tgz#fdfc8f7888f6e9ed0dae081f5f66b9f5429608a9"
integrity sha512-SgqDTCA5ux17KKTpEV2YC54ugBWU2jzpiFlCmVckPjYl5BhmOwuJ1Q5H/8v/XGcnHDqP31Ui4lk31Vts4NmtTA==
dependencies:
prosemirror-model "1.8.2"
prosemirror-state "1.3.2"
prosemirror-tables "1.0.0"
prosemirror-utils "0.9.6"
tiptap@^1.26.6:
version "1.26.6"
resolved "https://registry.yarnpkg.com/tiptap/-/tiptap-1.26.6.tgz#b287fa7cb1c20690868aee8dc526de5390b054f0"
integrity sha512-U5qyYZi5IH7LhYwYrStRBp5MxF5MiGFLt9ogOAF/0N/LIg0XwVwe/AaSx0UH/s4dY7R8OvEa9u4qimO08Wp1LA==
dependencies:
prosemirror-commands "1.1.2"
prosemirror-dropcursor "1.3.2"
prosemirror-gapcursor "1.1.2"
prosemirror-inputrules "1.1.2"
prosemirror-keymap "1.1.3"
prosemirror-model "1.8.2"
prosemirror-state "1.3.2"
prosemirror-view "1.13.4"
tiptap-commands "^1.12.5"
tiptap-utils "^1.8.3"
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@ -9013,11 +8802,6 @@ vue@^2.6.11:
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.11.tgz#76594d877d4b12234406e84e35275c6d514125c5"
integrity sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ==
w3c-keyname@^2.2.0:
version "2.2.2"
resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.2.tgz#7ea63170454bb19f1a3c6b628fc3dc8889276e91"
integrity sha512-8Vs/aVwcy0IJACaPm4tyzh1fzehZE70bGSjEl3dDms5UXtWnaBElrSHC8lDDeak0Gk5jxKOFstL64/65o7Ge2A==
watchpack@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00"

Loading…
Cancel
Save