Merge branch 'main' of github.com:ueberdosis/tiptap-next into main

This commit is contained in:
Hans Pagel 2020-11-05 09:38:29 +01:00
commit b7dbc4d9bc
78 changed files with 871 additions and 1076 deletions

View File

@ -40,10 +40,10 @@
<button @click="editor.chain().focus().heading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
h6
</button>
<button @click="editor.chain().focus().bulletList().run()" :class="{ 'is-active': editor.isActive('bullet_list') }">
<button @click="editor.chain().focus().bulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
bullet list
</button>
<button @click="editor.chain().focus().orderedList().run()" :class="{ 'is-active': editor.isActive('ordered_list') }">
<button @click="editor.chain().focus().orderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
ordered list
</button>
<button @click="editor.chain().focus().codeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">

View File

@ -1,6 +1,6 @@
<template>
<div v-if="editor">
<button @click="editor.chain().focus().bulletList().run()" :class="{ 'is-active': editor.isActive('bullet_list') }">
<button @click="editor.chain().focus().bulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
bullet list
</button>

View File

@ -1,9 +1,9 @@
<template>
<div v-if="editor">
<button @click="editor.chain().focus().bulletList().run()" :class="{ 'is-active': editor.isActive('bullet_list') }">
<button @click="editor.chain().focus().bulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
bullet list
</button>
<button @click="editor.chain().focus().orderedList().run()" :class="{ 'is-active': editor.isActive('ordered_list') }">
<button @click="editor.chain().focus().orderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
ordered list
</button>

View File

@ -1,6 +1,6 @@
<template>
<div v-if="editor">
<button @click="editor.chain().focus().orderedList().run()" :class="{ 'is-active': editor.isActive('ordered_list') }">
<button @click="editor.chain().focus().orderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
ordered list
</button>

View File

@ -12,15 +12,15 @@ context('/api/nodes/task-list', () => {
it('should parse unordered lists correctly', () => {
cy.get('.ProseMirror').then(([{ editor }]) => {
editor.setContent('<ul data-type="task_list"><li data-checked="true" data-type="task_item"><p>Example Text</p></li></ul>')
expect(editor.getHTML()).to.eq('<ul data-type="task_list"><li data-checked="true" data-type="task_item"><p>Example Text</p></li></ul>')
editor.setContent('<ul data-type="task_list"><li data-checked="true" data-type="taskItem"><p>Example Text</p></li></ul>')
expect(editor.getHTML()).to.eq('<ul data-type="task_list"><li data-checked="true" data-type="taskItem"><p>Example Text</p></li></ul>')
})
})
it('should parse unordered lists without paragraphs correctly', () => {
cy.get('.ProseMirror').then(([{ editor }]) => {
editor.setContent('<ul data-type="task_list"><li data-checked="false" data-type="task_item">Example Text</li></ul>')
expect(editor.getHTML()).to.eq('<ul data-type="task_list"><li data-checked="false" data-type="task_item"><p>Example Text</p></li></ul>')
editor.setContent('<ul data-type="task_list"><li data-checked="false" data-type="taskItem">Example Text</li></ul>')
expect(editor.getHTML()).to.eq('<ul data-type="task_list"><li data-checked="false" data-type="taskItem"><p>Example Text</p></li></ul>')
})
})

View File

@ -39,8 +39,8 @@ export default {
],
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>
<li data-type="taskItem" data-checked="true">A list item</li>
<li data-type="taskItem" data-checked="false">And another one</li>
</ul>
`,
})

View File

@ -24,7 +24,7 @@ yarn add @tiptap/extension-bullet-list @tiptap/extension-list-item
## Commands
| Command | Parameters | Description |
| ----------- | ---------- | --------------------- |
| bullet_list | — | Toggle a bullet list. |
| bulletList | — | Toggle a bullet list. |
## Keyboard shortcuts
* `Control`&nbsp;`Shift`&nbsp;`8`

View File

@ -189,6 +189,7 @@ $menuBreakPoint: 800px;
&::after {
content: 'draft';
font-family: 'JetBrainsMono', monospace;
text-transform: uppercase;
color: $colorGrey;
background-color: rgba($colorGrey, 0.1);
padding: 0 0.5em;
@ -200,6 +201,7 @@ $menuBreakPoint: 800px;
&::after {
content: 'PRO';
font-family: 'JetBrainsMono', monospace;
text-transform: uppercase;
color: $colorOrange;
background-color: rgba($colorOrange, 0.1);
padding: 0 0.5em;

View File

@ -131,7 +131,7 @@ export default class CommandManager {
view,
state: this.chainableState(tr, state),
dispatch: shouldDispatch
? () => true
? () => undefined
: undefined,
chain: () => this.createChain(tr),
can: () => this.createCan(tr),

View File

@ -261,15 +261,20 @@ export class Editor extends EventEmitter {
*/
private createView() {
this.view = new EditorView(this.options.element, {
dispatchTransaction: this.dispatchTransaction.bind(this),
state: EditorState.create({
doc: this.createDocument(this.options.content),
plugins: this.extensionManager.plugins,
}),
dispatchTransaction: this.dispatchTransaction.bind(this),
})
// `editor.view` is not yet available at this time.
// Therefore we will add all node views directly afterwards.
// Therefore we will add all plugins and node views directly afterwards.
const newState = this.state.reconfigure({
plugins: this.extensionManager.plugins,
})
this.view.updateState(newState)
this.view.setProps({
nodeViews: this.extensionManager.nodeViews,
})

View File

@ -0,0 +1,9 @@
import { Command } from '../Editor'
export default (): Command => ({ view }) => {
const element = view.dom as HTMLElement
element.blur()
return true
}

View File

@ -0,0 +1,5 @@
import { Command } from '../Editor'
export default (emitUpdate: Boolean = false): Command => ({ commands }) => {
return commands.setContent('', emitUpdate)
}

View File

@ -0,0 +1,29 @@
import { liftTarget } from 'prosemirror-transform'
import { Command } from '../Editor'
export default (): Command => ({ state, tr, dispatch }) => {
const { selection } = tr
const { from, to } = selection
state.doc.nodesBetween(from, to, (node, pos) => {
if (!node.type.isText) {
const fromPos = tr.doc.resolve(tr.mapping.map(pos + 1))
const toPos = tr.doc.resolve(tr.mapping.map(pos + node.nodeSize - 1))
const nodeRange = fromPos.blockRange(toPos)
if (nodeRange) {
const targetLiftDepth = liftTarget(nodeRange)
if (node.type.isTextblock && dispatch) {
tr.setNodeMarkup(nodeRange.start, state.schema.nodes.paragraph)
}
if ((targetLiftDepth || targetLiftDepth === 0) && dispatch) {
tr.lift(nodeRange, targetLiftDepth)
}
}
}
})
return true
}

View File

@ -0,0 +1,6 @@
import { deleteSelection } from 'prosemirror-commands'
import { Command } from '../Editor'
export default (): Command => ({ state, dispatch }) => {
return deleteSelection(state, dispatch)
}

View File

@ -0,0 +1,58 @@
import { TextSelection } from 'prosemirror-state'
import { Editor, Command } from '../Editor'
import minMax from '../utils/minMax'
type Position = 'start' | 'end' | number | boolean | null
interface ResolvedSelection {
from: number,
to: number,
}
function resolveSelection(editor: Editor, position: Position = null): ResolvedSelection {
if (position === null) {
return editor.selection
}
if (position === 'start' || position === true) {
return {
from: 0,
to: 0,
}
}
if (position === 'end') {
const { size } = editor.state.doc.content
return {
from: size,
to: size - 1, // TODO: -1 only for nodes with content
}
}
return {
from: position as number,
to: position as number,
}
}
export default (position: Position = null): Command => ({
editor, view, tr, dispatch,
}) => {
if ((view.hasFocus() && position === null) || position === false) {
return true
}
const { from, to } = resolveSelection(editor, position)
const { doc } = tr
const resolvedFrom = minMax(from, 0, doc.content.size)
const resolvedEnd = minMax(to, 0, doc.content.size)
const selection = TextSelection.create(doc, resolvedFrom, resolvedEnd)
if (dispatch) {
tr.setSelection(selection)
view.focus()
}
return true
}

View File

@ -3,7 +3,6 @@ import { Selection, Transaction } from 'prosemirror-state'
import { ReplaceStep, ReplaceAroundStep } from 'prosemirror-transform'
import elementFromString from '../utils/elementFromString'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
// TODO: move to utils
// https://github.com/ProseMirror/prosemirror-state/blob/master/src/selection.js#L466
@ -18,27 +17,15 @@ function selectionToInsertionEnd(tr: Transaction, startLen: number, bias: number
tr.setSelection(Selection.near(tr.doc.resolve(end as unknown as number), bias))
}
export const InsertHTML = createExtension({
addCommands() {
return {
insertHTML: (value: string): Command => ({ tr, state, dispatch }) => {
const { selection } = tr
const element = elementFromString(value)
const slice = DOMParser.fromSchema(state.schema).parseSlice(element)
export default (value: string): Command => ({ tr, state, dispatch }) => {
const { selection } = tr
const element = elementFromString(value)
const slice = DOMParser.fromSchema(state.schema).parseSlice(element)
if (dispatch) {
tr.insert(selection.anchor, slice.content)
selectionToInsertionEnd(tr, tr.steps.length - 1, -1)
}
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
InsertHTML: typeof InsertHTML,
if (dispatch) {
tr.insert(selection.anchor, slice.content)
selectionToInsertionEnd(tr, tr.steps.length - 1, -1)
}
return true
}

View File

@ -0,0 +1,9 @@
import { Command } from '../Editor'
export default (value: string): Command => ({ tr, dispatch }) => {
if (dispatch) {
tr.insertText(value)
}
return true
}

View File

@ -0,0 +1,10 @@
import { liftListItem } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import getNodeType from '../utils/getNodeType'
export default (typeOrName: string | NodeType): Command => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return liftListItem(type)(state, dispatch)
}

View File

@ -0,0 +1,26 @@
import { MarkType } from 'prosemirror-model'
import { Command } from '../Editor'
import getMarkType from '../utils/getMarkType'
import getMarkRange from '../utils/getMarkRange'
export default (typeOrName: string | MarkType): Command => ({ tr, state, dispatch }) => {
const { selection } = tr
const type = getMarkType(typeOrName, state.schema)
let { from, to } = selection
const { $from, empty } = selection
if (empty) {
const range = getMarkRange($from, type)
if (range) {
from = range.from
to = range.to
}
}
if (dispatch) {
tr.removeMark(from, to, type)
}
return true
}

View File

@ -0,0 +1,20 @@
import { Command } from '../Editor'
export default (): Command => ({ tr, state, dispatch }) => {
const { selection } = tr
const { from, to, empty } = selection
if (empty) {
return true
}
if (dispatch) {
Object
.entries(state.schema.marks)
.forEach(([, mark]) => {
tr.removeMark(from, to, mark as any)
})
}
return true
}

View File

@ -0,0 +1,23 @@
import { Command } from '../Editor'
export default (attributeNames: string[] = []): Command => ({ tr, state, dispatch }) => {
const { selection } = tr
const { from, to } = selection
state.doc.nodesBetween(from, to, (node, pos) => {
if (!node.type.isText) {
attributeNames.forEach(name => {
const attribute = node.type.spec.attrs?.[name]
const defaultValue = attribute?.default
if (attribute && defaultValue !== undefined && dispatch) {
tr.setNodeMarkup(pos, undefined, {
[name]: defaultValue,
})
}
})
}
})
return true
}

View File

@ -0,0 +1,9 @@
import { Command } from '../Editor'
export default (): Command => ({ tr, dispatch }) => {
if (dispatch) {
tr.scrollIntoView()
}
return true
}

View File

@ -0,0 +1,6 @@
import { selectAll } from 'prosemirror-commands'
import { Command } from '../Editor'
export default (): Command => ({ state, dispatch }) => {
return selectAll(state, dispatch)
}

View File

@ -0,0 +1,6 @@
import { selectParentNode } from 'prosemirror-commands'
import { Command } from '../Editor'
export default (): Command => ({ state, dispatch }) => {
return selectParentNode(state, dispatch)
}

View File

@ -0,0 +1,10 @@
import { NodeType } from 'prosemirror-model'
import { setBlockType } from 'prosemirror-commands'
import { Command } from '../Editor'
import getNodeType from '../utils/getNodeType'
export default (typeOrName: string | NodeType, attrs = {}): Command => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return setBlockType(type, attrs)(state, dispatch)
}

View File

@ -0,0 +1,17 @@
import { TextSelection } from 'prosemirror-state'
import { Command } from '../Editor'
export default (content: string, emitUpdate: Boolean = false, parseOptions = {}): Command => ({ tr, editor, dispatch }) => {
const { createDocument } = editor
const { doc } = tr
const document = createDocument(content, parseOptions)
const selection = TextSelection.create(doc, 0, doc.content.size)
if (dispatch) {
tr.setSelection(selection)
.replaceSelectionWith(document, false)
.setMeta('preventUpdate', !emitUpdate)
}
return true
}

View File

@ -0,0 +1,14 @@
import { Command } from '../Editor'
export default (attributes: {}): Command => ({ tr, state, dispatch }) => {
const { selection } = tr
const { from, to } = selection
state.doc.nodesBetween(from, to, (node, pos) => {
if (!node.type.isText && dispatch) {
tr.setNodeMarkup(pos, undefined, attributes)
}
})
return true
}

View File

@ -0,0 +1,10 @@
import { sinkListItem as originalSinkListItem } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import getNodeType from '../utils/getNodeType'
export default (typeOrName: string | NodeType): Command => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return originalSinkListItem(type)(state, dispatch)
}

View File

@ -0,0 +1,117 @@
import { canSplit } from 'prosemirror-transform'
import { ContentMatch, Fragment } from 'prosemirror-model'
import { EditorState, NodeSelection, TextSelection } from 'prosemirror-state'
import { Command } from '../Editor'
function defaultBlockAt(match: ContentMatch) {
for (let i = 0; i < match.edgeCount; i + 1) {
const { type } = match.edge(i)
// @ts-ignore
if (type.isTextblock && !type.hasRequiredAttrs()) return type
}
return null
}
export interface SplitBlockOptions {
withAttributes: boolean,
withMarks: boolean,
}
function keepMarks(state: EditorState) {
const marks = state.storedMarks
|| (state.selection.$to.parentOffset && state.selection.$from.marks())
if (marks) {
state.tr.ensureMarks(marks)
}
}
export default (options: Partial<SplitBlockOptions> = {}): Command => ({ tr, state, dispatch }) => {
const defaultOptions: SplitBlockOptions = {
withAttributes: false,
withMarks: true,
}
const config = { ...defaultOptions, ...options }
const { selection, doc } = tr
const { $from, $to } = selection
if (selection instanceof NodeSelection && selection.node.isBlock) {
if (!$from.parentOffset || !canSplit(doc, $from.pos)) {
return false
}
if (dispatch) {
if (config.withMarks) {
keepMarks(state)
}
tr.split($from.pos).scrollIntoView()
}
return true
}
if (!$from.parent.isBlock) {
return false
}
if (dispatch) {
const atEnd = $to.parentOffset === $to.parent.content.size
if (selection instanceof TextSelection) {
tr.deleteSelection()
}
const deflt = $from.depth === 0
? undefined
: defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)))
let types = atEnd && deflt
? [{
type: deflt,
attrs: config.withAttributes
? $from.node().attrs
: {},
}]
: undefined
let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types)
if (
!types
&& !can
&& canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : undefined)
) {
can = true
types = deflt
? [{
type: deflt,
attrs: config.withAttributes
? $from.node().attrs
: {},
}]
: undefined
}
if (can) {
tr.split(tr.mapping.map($from.pos), 1, types)
if (
!atEnd
&& !$from.parentOffset
&& $from.parent.type !== deflt
&& $from.node(-1).canReplace($from.index(-1), $from.indexAfter(-1), Fragment.from(deflt?.create()))
) {
tr.setNodeMarkup(tr.mapping.map($from.before()), deflt || undefined)
}
}
if (config.withMarks) {
keepMarks(state)
}
tr.scrollIntoView()
}
return true
}

View File

@ -0,0 +1,10 @@
import { splitListItem } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import getNodeType from '../utils/getNodeType'
export default (typeOrName: string | NodeType): Command => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return splitListItem(type)(state, dispatch)
}

View File

@ -0,0 +1,16 @@
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import nodeIsActive from '../utils/nodeIsActive'
import getNodeType from '../utils/getNodeType'
export default (typeOrName: string | NodeType, toggleTypeOrName: string | NodeType, attrs = {}): Command => ({ state, commands }) => {
const type = getNodeType(typeOrName, state.schema)
const toggleType = getNodeType(toggleTypeOrName, state.schema)
const isActive = nodeIsActive(state, type, attrs)
if (isActive) {
return commands.setBlockType(toggleType)
}
return commands.setBlockType(type, attrs)
}

View File

@ -0,0 +1,52 @@
import { findParentNode } from 'prosemirror-utils'
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import getNodeType from '../utils/getNodeType'
import isList from '../utils/isList'
export default (listTypeOrName: string | NodeType, itemTypeOrName: string | NodeType): Command => ({
editor, tr, state, dispatch, chain, commands, can,
}) => {
const { extensions } = editor.options
const listType = getNodeType(listTypeOrName, state.schema)
const itemType = getNodeType(itemTypeOrName, state.schema)
const { selection } = state
const { $from, $to } = selection
const range = $from.blockRange($to)
if (!range) {
return false
}
const parentList = findParentNode(node => isList(node.type.name, extensions))(selection)
if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
// remove list
if (parentList.node.type === listType) {
return commands.liftListItem(itemType)
}
// change list type
if (
isList(parentList.node.type.name, extensions)
&& listType.validContent(parentList.node.content)
&& dispatch
) {
tr.setNodeMarkup(parentList.pos, listType)
return true
}
}
const canWrapInList = can().wrapInList(listType)
// try to convert node to paragraph if needed
if (!canWrapInList) {
return chain()
.clearNodes()
.wrapInList(listType)
.run()
}
return commands.wrapInList(listType)
}

View File

@ -0,0 +1,10 @@
import { toggleMark as originalToggleMark } from 'prosemirror-commands'
import { MarkType } from 'prosemirror-model'
import { Command } from '../Editor'
import getMarkType from '../utils/getMarkType'
export default (typeOrName: string | MarkType): Command => ({ state, dispatch }) => {
const type = getMarkType(typeOrName, state.schema)
return originalToggleMark(type)(state, dispatch)
}

View File

@ -0,0 +1,16 @@
import { wrapIn, lift } from 'prosemirror-commands'
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import nodeIsActive from '../utils/nodeIsActive'
import getNodeType from '../utils/getNodeType'
export default (typeOrName: string | NodeType, attrs = {}): Command => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
const isActive = nodeIsActive(state, type, attrs)
if (isActive) {
return lift(state, dispatch)
}
return wrapIn(type, attrs)(state, dispatch)
}

View File

@ -0,0 +1,15 @@
import { Command } from '../Editor'
export default (commands: Command[] | ((props: Parameters<Command>[0]) => Command[])): Command => props => {
const items = typeof commands === 'function'
? commands(props)
: commands
for (let i = 0; i < items.length; i += 1) {
if (items[i](props)) {
return true
}
}
return false
}

View File

@ -0,0 +1,32 @@
import { MarkType } from 'prosemirror-model'
import { Command } from '../Editor'
import getMarkType from '../utils/getMarkType'
import getMarkRange from '../utils/getMarkRange'
export default (typeOrName: string | MarkType, attrs: {}): Command => ({ tr, state, dispatch }) => {
const { selection, doc } = tr
let { from, to } = selection
const { $from, empty } = selection
const type = getMarkType(typeOrName, state.schema)
if (empty) {
const range = getMarkRange($from, type)
if (range) {
from = range.from
to = range.to
}
}
const hasMark = doc.rangeHasMark(from, to, type)
if (hasMark && dispatch) {
tr.removeMark(from, to, type)
}
if (dispatch) {
tr.addMark(from, to, type.create(attrs))
}
return true
}

View File

@ -0,0 +1,10 @@
import { wrapInList } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import getNodeType from '../utils/getNodeType'
export default (typeOrName: string | NodeType, attrs?: {}): Command => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return wrapInList(type, attrs)(state, dispatch)
}

View File

@ -1,14 +0,0 @@
import { baseKeymap } from 'prosemirror-commands'
import { createExtension } from '../Extension'
export const BaseKeymap = createExtension({
addKeyboardShortcuts() {
return baseKeymap
},
})
declare module '../Editor' {
interface AllExtensions {
BaseKeymap: typeof BaseKeymap,
}
}

View File

@ -1,22 +0,0 @@
import { Command } from '../Editor'
import { createExtension } from '../Extension'
export const Blur = createExtension({
addCommands() {
return {
blur: (): Command => ({ view }) => {
const element = view.dom as HTMLElement
element.blur()
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
Blur: typeof Blur,
}
}

View File

@ -1,18 +0,0 @@
import { Command } from '../Editor'
import { createExtension } from '../Extension'
export const ClearContent = createExtension({
addCommands() {
return {
clearContent: (emitUpdate: Boolean = false): Command => ({ commands }) => {
return commands.setContent('', emitUpdate)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
ClearContent: typeof ClearContent,
}
}

View File

@ -1,42 +0,0 @@
import { liftTarget } from 'prosemirror-transform'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
export const ClearNodes = createExtension({
addCommands() {
return {
clearNodes: (): Command => ({ state, tr, dispatch }) => {
const { selection } = tr
const { from, to } = selection
state.doc.nodesBetween(from, to, (node, pos) => {
if (!node.type.isText) {
const fromPos = tr.doc.resolve(tr.mapping.map(pos + 1))
const toPos = tr.doc.resolve(tr.mapping.map(pos + node.nodeSize - 1))
const nodeRange = fromPos.blockRange(toPos)
if (nodeRange) {
const targetLiftDepth = liftTarget(nodeRange)
if (node.type.isTextblock && dispatch) {
tr.setNodeMarkup(nodeRange.start, state.schema.nodes.paragraph)
}
if ((targetLiftDepth || targetLiftDepth === 0) && dispatch) {
tr.lift(nodeRange, targetLiftDepth)
}
}
}
})
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
ClearNodes: typeof ClearNodes,
}
}

View File

@ -0,0 +1,68 @@
import { createExtension } from '../Extension'
import blur from '../commands/blur'
import clearContent from '../commands/clearContent'
import clearNodes from '../commands/clearNodes'
import deleteSelection from '../commands/deleteSelection'
import focus from '../commands/focus'
import insertHTML from '../commands/insertHTML'
import insertText from '../commands/insertText'
import liftListItem from '../commands/liftListItem'
import removeMark from '../commands/removeMark'
import removeMarks from '../commands/removeMarks'
import resetNodeAttributes from '../commands/resetNodeAttributes'
import scrollIntoView from '../commands/scrollIntoView'
import selectAll from '../commands/selectAll'
import selectParentNode from '../commands/selectParentNode'
import setBlockType from '../commands/setBlockType'
import setContent from '../commands/setContent'
import setNodeAttributes from '../commands/setNodeAttributes'
import sinkListItem from '../commands/sinkListItem'
import splitBlock from '../commands/splitBlock'
import splitListItem from '../commands/splitListItem'
import toggleBlockType from '../commands/toggleBlockType'
import toggleList from '../commands/toggleList'
import toggleMark from '../commands/toggleMark'
import toggleWrap from '../commands/toggleWrap'
import tryCommand from '../commands/try'
import updateMark from '../commands/updateMark'
import wrapInList from '../commands/wrapInList'
export const Commands = createExtension({
addCommands() {
return {
blur,
clearContent,
clearNodes,
deleteSelection,
focus,
insertHTML,
insertText,
liftListItem,
removeMark,
removeMarks,
resetNodeAttributes,
scrollIntoView,
selectAll,
selectParentNode,
setBlockType,
setContent,
setNodeAttributes,
sinkListItem,
splitBlock,
splitListItem,
toggleBlockType,
toggleList,
toggleMark,
toggleWrap,
try: tryCommand,
updateMark,
wrapInList,
}
},
})
declare module '../Editor' {
interface AllExtensions {
Commands: typeof Commands,
}
}

View File

@ -1,19 +0,0 @@
import { deleteSelection } from 'prosemirror-commands'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
export const DeleteSelection = createExtension({
addCommands() {
return {
deleteSelection: (): Command => ({ state, dispatch }) => {
return deleteSelection(state, dispatch)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
DeleteSelection: typeof DeleteSelection,
}
}

View File

@ -13,3 +13,10 @@ export const Editable = createExtension({
]
},
})
// TODO: Editable circularly references itself!?
// declare module '../Editor' {
// interface AllExtensions {
// Editable: typeof Editable,
// }
// }

View File

@ -1,72 +0,0 @@
import { TextSelection } from 'prosemirror-state'
import { Editor, Command } from '../Editor'
import { createExtension } from '../Extension'
import minMax from '../utils/minMax'
type Position = 'start' | 'end' | number | boolean | null
interface ResolvedSelection {
from: number,
to: number,
}
function resolveSelection(editor: Editor, position: Position = null): ResolvedSelection {
if (position === null) {
return editor.selection
}
if (position === 'start' || position === true) {
return {
from: 0,
to: 0,
}
}
if (position === 'end') {
const { size } = editor.state.doc.content
return {
from: size,
to: size - 1, // TODO: -1 only for nodes with content
}
}
return {
from: position as number,
to: position as number,
}
}
export const Focus = createExtension({
addCommands() {
return {
focus: (position: Position = null): Command => ({
editor, view, tr, dispatch,
}) => {
if ((view.hasFocus() && position === null) || position === false) {
return true
}
const { from, to } = resolveSelection(editor, position)
const { doc } = tr
const resolvedFrom = minMax(from, 0, doc.content.size)
const resolvedEnd = minMax(to, 0, doc.content.size)
const selection = TextSelection.create(doc, resolvedFrom, resolvedEnd)
if (dispatch) {
tr.setSelection(selection)
}
view.focus()
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
Focus: typeof Focus,
}
}

View File

@ -1,30 +1,4 @@
export { Blur } from './blur'
export { ClearContent } from './clearContent'
export { ClearNodes } from './clearNodes'
export { DeleteSelection } from './deleteSelection'
export { Commands } from './commands'
export { Editable } from './editable'
export { Focus } from './focus'
export { FocusEvents } from './focusEvents'
export { InputRules } from './inputRules'
export { InsertHTML } from './insertHTML'
export { InsertText } from './insertText'
export { BaseKeymap } from './baseKeymap'
export { LiftListItem } from './liftListItem'
export { RemoveMark } from './removeMark'
export { RemoveMarks } from './removeMarks'
export { ScrollIntoView } from './scrollIntoView'
export { SelectAll } from './selectAll'
export { SelectParentNode } from './selectParentNode'
export { ResetNodeAttributes } from './resetNodeAttributes'
export { SetNodeAttributes } from './setNodeAttributes'
export { SetBlockType } from './setBlockType'
export { SetContent } from './setContent'
export { SinkListItem } from './sinkListItem'
export { SplitBlock } from './splitBlock'
export { SplitListItem } from './splitListItem'
export { ToggleBlockType } from './toggleBlockType'
export { ToggleList } from './toggleList'
export { ToggleMark } from './toggleMark'
export { UpdateMark } from './updateMark'
export { ToggleWrap } from './toggleWrap'
export { WrapInList } from './wrapInList'
export { Keymap } from './keymap'

View File

@ -1,16 +0,0 @@
import { undoInputRule } from 'prosemirror-inputrules'
import { createExtension } from '../Extension'
export const InputRules = createExtension({
addKeyboardShortcuts() {
return {
Backspace: undoInputRule,
}
},
})
declare module '../Editor' {
interface AllExtensions {
InputRules: typeof InputRules,
}
}

View File

@ -1,22 +0,0 @@
import { Command } from '../Editor'
import { createExtension } from '../Extension'
export const InsertText = createExtension({
addCommands() {
return {
insertText: (value: string): Command => ({ tr, dispatch }) => {
if (dispatch) {
tr.insertText(value)
}
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
InsertText: typeof InsertText,
}
}

View File

@ -0,0 +1,52 @@
import {
newlineInCode,
createParagraphNear,
liftEmptyBlock,
exitCode,
deleteSelection,
joinForward,
joinBackward,
selectNodeForward,
selectNodeBackward,
} from 'prosemirror-commands'
import { undoInputRule } from 'prosemirror-inputrules'
import { createExtension } from '../Extension'
export const Keymap = createExtension({
addKeyboardShortcuts() {
const handleBackspace = () => this.editor.try(({ state, dispatch }) => [
() => undoInputRule(state, dispatch),
() => deleteSelection(state, dispatch),
() => joinBackward(state, dispatch),
() => selectNodeBackward(state, dispatch),
])
const handleDelete = () => this.editor.try(({ state, dispatch }) => [
() => deleteSelection(state, dispatch),
() => joinForward(state, dispatch),
() => selectNodeForward(state, dispatch),
])
return {
Enter: () => this.editor.try(({ commands, state, dispatch }) => [
() => newlineInCode(state, dispatch),
() => createParagraphNear(state, dispatch),
() => liftEmptyBlock(state, dispatch),
() => commands.splitBlock(),
]),
'Mod-Enter': exitCode,
Backspace: () => handleBackspace(),
'Mod-Backspace': () => handleBackspace(),
Delete: () => handleDelete(),
'Mod-Delete': () => handleDelete(),
// we dont need a custom `selectAll` for now
// 'Mod-a': () => this.editor.selectAll(),
}
},
})
declare module '../Editor' {
interface AllExtensions {
Keymap: typeof Keymap,
}
}

View File

@ -1,23 +0,0 @@
import { liftListItem } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
import getNodeType from '../utils/getNodeType'
export const LiftListItem = createExtension({
addCommands() {
return {
liftListItem: (typeOrName: string | NodeType): Command => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return liftListItem(type)(state, dispatch)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
LiftListItem: typeof LiftListItem,
}
}

View File

@ -1,39 +0,0 @@
import { MarkType } from 'prosemirror-model'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
import getMarkType from '../utils/getMarkType'
import getMarkRange from '../utils/getMarkRange'
export const RemoveMark = createExtension({
addCommands() {
return {
removeMark: (typeOrName: string | MarkType): Command => ({ tr, state, dispatch }) => {
const { selection } = tr
const type = getMarkType(typeOrName, state.schema)
let { from, to } = selection
const { $from, empty } = selection
if (empty) {
const range = getMarkRange($from, type)
if (range) {
from = range.from
to = range.to
}
}
if (dispatch) {
tr.removeMark(from, to, type)
}
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
RemoveMark: typeof RemoveMark,
}
}

View File

@ -1,33 +0,0 @@
import { Command } from '../Editor'
import { createExtension } from '../Extension'
export const RemoveMarks = createExtension({
addCommands() {
return {
removeMarks: (): Command => ({ tr, state, dispatch }) => {
const { selection } = tr
const { from, to, empty } = selection
if (empty) {
return true
}
if (dispatch) {
Object
.entries(state.schema.marks)
.forEach(([, mark]) => {
tr.removeMark(from, to, mark as any)
})
}
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
RemoveMarks: typeof RemoveMarks,
}
}

View File

@ -1,36 +0,0 @@
import { Command } from '../Editor'
import { createExtension } from '../Extension'
export const ResetNodeAttributes = createExtension({
addCommands() {
return {
resetNodeAttributes: (attributeNames: string[] = []): Command => ({ tr, state, dispatch }) => {
const { selection } = tr
const { from, to } = selection
state.doc.nodesBetween(from, to, (node, pos) => {
if (!node.type.isText) {
attributeNames.forEach(name => {
const attribute = node.type.spec.attrs?.[name]
const defaultValue = attribute?.default
if (attribute && defaultValue !== undefined && dispatch) {
tr.setNodeMarkup(pos, undefined, {
[name]: defaultValue,
})
}
})
}
})
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
ResetNodeAttributes: typeof ResetNodeAttributes,
}
}

View File

@ -1,22 +0,0 @@
import { Command } from '../Editor'
import { createExtension } from '../Extension'
export const ScrollIntoView = createExtension({
addCommands() {
return {
scrollIntoView: (): Command => ({ tr, dispatch }) => {
if (dispatch) {
tr.scrollIntoView()
}
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
ScrollIntoView: typeof ScrollIntoView,
}
}

View File

@ -1,19 +0,0 @@
import { selectAll } from 'prosemirror-commands'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
export const SelectAll = createExtension({
addCommands() {
return {
selectAll: (): Command => ({ state, dispatch }) => {
return selectAll(state, dispatch)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
SelectAll: typeof SelectAll,
}
}

View File

@ -1,19 +0,0 @@
import { selectParentNode } from 'prosemirror-commands'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
export const SelectParentNode = createExtension({
addCommands() {
return {
selectParentNode: (): Command => ({ state, dispatch }) => {
return selectParentNode(state, dispatch)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
SelectParentNode: typeof SelectParentNode,
}
}

View File

@ -1,23 +0,0 @@
import { NodeType } from 'prosemirror-model'
import { setBlockType } from 'prosemirror-commands'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
import getNodeType from '../utils/getNodeType'
export const SetBlockType = createExtension({
addCommands() {
return {
setBlockType: (typeOrName: string | NodeType, attrs = {}): Command => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return setBlockType(type, attrs)(state, dispatch)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
SetBlockType: typeof SetBlockType,
}
}

View File

@ -1,30 +0,0 @@
import { TextSelection } from 'prosemirror-state'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
export const SetContent = createExtension({
addCommands() {
return {
setContent: (content: string, emitUpdate: Boolean = false, parseOptions = {}): Command => ({ tr, editor, dispatch }) => {
const { createDocument } = editor
const { doc } = tr
const document = createDocument(content, parseOptions)
const selection = TextSelection.create(doc, 0, doc.content.size)
if (dispatch) {
tr.setSelection(selection)
.replaceSelectionWith(document, false)
.setMeta('preventUpdate', !emitUpdate)
}
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
SetContent: typeof SetContent,
}
}

View File

@ -1,27 +0,0 @@
import { Command } from '../Editor'
import { createExtension } from '../Extension'
export const SetNodeAttributes = createExtension({
addCommands() {
return {
setNodeAttributes: (attributes: {}): Command => ({ tr, state, dispatch }) => {
const { selection } = tr
const { from, to } = selection
state.doc.nodesBetween(from, to, (node, pos) => {
if (!node.type.isText && dispatch) {
tr.setNodeMarkup(pos, undefined, attributes)
}
})
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
SetNodeAttributes: typeof SetNodeAttributes,
}
}

View File

@ -1,23 +0,0 @@
import { sinkListItem as originalSinkListItem } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
import getNodeType from '../utils/getNodeType'
export const SinkListItem = createExtension({
addCommands() {
return {
sinkListItem: (typeOrName: string | NodeType): Command => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return originalSinkListItem(type)(state, dispatch)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
SinkListItem: typeof SinkListItem,
}
}

View File

@ -1,93 +0,0 @@
import { canSplit } from 'prosemirror-transform'
import { ContentMatch, Fragment } from 'prosemirror-model'
import { NodeSelection, TextSelection } from 'prosemirror-state'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
function defaultBlockAt(match: ContentMatch) {
for (let i = 0; i < match.edgeCount; i + 1) {
const { type } = match.edge(i)
// @ts-ignore
if (type.isTextblock && !type.hasRequiredAttrs()) return type
}
return null
}
export const SplitBlock = createExtension({
addCommands() {
return {
splitBlock: (copyAttributes = false): Command => ({ tr, dispatch }) => {
const { selection, doc } = tr
const { $from, $to } = selection
if (selection instanceof NodeSelection && selection.node.isBlock) {
if (!$from.parentOffset || !canSplit(doc, $from.pos)) {
return false
}
if (dispatch) {
tr.split($from.pos).scrollIntoView()
}
return true
}
if (!$from.parent.isBlock) {
return false
}
if (dispatch) {
const atEnd = $to.parentOffset === $to.parent.content.size
if (selection instanceof TextSelection) {
tr.deleteSelection()
}
const deflt = $from.depth === 0
? undefined
: defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)))
let types = atEnd && deflt
? [{ type: deflt, attrs: copyAttributes ? $from.node().attrs : {} }]
: undefined
let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types)
if (
!types
&& !can
&& canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : undefined)
) {
can = true
types = deflt
? [{ type: deflt, attrs: copyAttributes ? $from.node().attrs : {} }]
: undefined
}
if (can) {
tr.split(tr.mapping.map($from.pos), 1, types)
if (
!atEnd
&& !$from.parentOffset
&& $from.parent.type !== deflt
&& $from.node(-1).canReplace($from.index(-1), $from.indexAfter(-1), Fragment.from(deflt?.create()))
) {
tr.setNodeMarkup(tr.mapping.map($from.before()), deflt || undefined)
}
}
tr.scrollIntoView()
}
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
SplitBlock: typeof SplitBlock,
}
}

View File

@ -1,23 +0,0 @@
import { splitListItem } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
import getNodeType from '../utils/getNodeType'
export const SplitListItem = createExtension({
addCommands() {
return {
splitListItem: (typeOrName: string | NodeType): Command => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return splitListItem(type)(state, dispatch)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
SplitListItem: typeof SplitListItem,
}
}

View File

@ -1,29 +0,0 @@
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
import nodeIsActive from '../utils/nodeIsActive'
import getNodeType from '../utils/getNodeType'
export const ToggleBlockType = createExtension({
addCommands() {
return {
toggleBlockType: (typeOrName: string | NodeType, toggleTypeOrName: string | NodeType, attrs = {}): Command => ({ state, commands }) => {
const type = getNodeType(typeOrName, state.schema)
const toggleType = getNodeType(toggleTypeOrName, state.schema)
const isActive = nodeIsActive(state, type, attrs)
if (isActive) {
return commands.setBlockType(toggleType)
}
return commands.setBlockType(type, attrs)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
ToggleBlockType: typeof ToggleBlockType,
}
}

View File

@ -1,65 +0,0 @@
import { findParentNode } from 'prosemirror-utils'
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
import getNodeType from '../utils/getNodeType'
import isList from '../utils/isList'
export const ToggleList = createExtension({
addCommands() {
return {
toggleList: (listTypeOrName: string | NodeType, itemTypeOrName: string | NodeType): Command => ({
tr, state, dispatch, chain, commands, can,
}) => {
const { extensions } = this.editor.options
const listType = getNodeType(listTypeOrName, state.schema)
const itemType = getNodeType(itemTypeOrName, state.schema)
const { selection } = state
const { $from, $to } = selection
const range = $from.blockRange($to)
if (!range) {
return false
}
const parentList = findParentNode(node => isList(node.type.name, extensions))(selection)
if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
// remove list
if (parentList.node.type === listType) {
return commands.liftListItem(itemType)
}
// change list type
if (
isList(parentList.node.type.name, extensions)
&& listType.validContent(parentList.node.content)
&& dispatch
) {
tr.setNodeMarkup(parentList.pos, listType)
return true
}
}
const canWrapInList = can().wrapInList(listType)
// try to convert node to paragraph if needed
if (!canWrapInList) {
return chain()
.clearNodes()
.wrapInList(listType)
.run()
}
return commands.wrapInList(listType)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
ToggleList: typeof ToggleList,
}
}

View File

@ -1,23 +0,0 @@
import { toggleMark as originalToggleMark } from 'prosemirror-commands'
import { MarkType } from 'prosemirror-model'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
import getMarkType from '../utils/getMarkType'
export const ToggleMark = createExtension({
addCommands() {
return {
toggleMark: (typeOrName: string | MarkType): Command => ({ state, dispatch }) => {
const type = getMarkType(typeOrName, state.schema)
return originalToggleMark(type)(state, dispatch)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
ToggleMark: typeof ToggleMark,
}
}

View File

@ -1,29 +0,0 @@
import { wrapIn, lift } from 'prosemirror-commands'
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
import nodeIsActive from '../utils/nodeIsActive'
import getNodeType from '../utils/getNodeType'
export const ToggleWrap = createExtension({
addCommands() {
return {
toggleWrap: (typeOrName: string | NodeType, attrs = {}): Command => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
const isActive = nodeIsActive(state, type, attrs)
if (isActive) {
return lift(state, dispatch)
}
return wrapIn(type, attrs)(state, dispatch)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
ToggleWrap: typeof ToggleWrap,
}
}

View File

@ -1,45 +0,0 @@
import { MarkType } from 'prosemirror-model'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
import getMarkType from '../utils/getMarkType'
import getMarkRange from '../utils/getMarkRange'
export const UpdateMark = createExtension({
addCommands() {
return {
updateMark: (typeOrName: string | MarkType, attrs: {}): Command => ({ tr, state, dispatch }) => {
const { selection, doc } = tr
let { from, to } = selection
const { $from, empty } = selection
const type = getMarkType(typeOrName, state.schema)
if (empty) {
const range = getMarkRange($from, type)
if (range) {
from = range.from
to = range.to
}
}
const hasMark = doc.rangeHasMark(from, to, type)
if (hasMark && dispatch) {
tr.removeMark(from, to, type)
}
if (dispatch) {
tr.addMark(from, to, type.create(attrs))
}
return true
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
UpdateMark: typeof UpdateMark,
}
}

View File

@ -1,23 +0,0 @@
import { wrapInList } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { Command } from '../Editor'
import { createExtension } from '../Extension'
import getNodeType from '../utils/getNodeType'
export const WrapInList = createExtension({
addCommands() {
return {
wrapInList: (typeOrName: string | NodeType, attrs?: {}): Command => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return wrapInList(type, attrs)(state, dispatch)
},
}
},
})
declare module '../Editor' {
interface AllExtensions {
WrapInList: typeof WrapInList,
}
}

View File

@ -16,9 +16,11 @@ function getMarksBetween(start: number, end: number, state: EditorState) {
return marks
}
export default function (regexp: RegExp, markType: MarkType, getAttrs?: Function) {
export default function (regexp: RegExp, markType: MarkType, getAttributes?: Function) {
return new InputRule(regexp, (state, match, start, end) => {
const attributes = getAttrs instanceof Function ? getAttrs(match) : getAttrs
const attributes = getAttributes instanceof Function
? getAttributes(match)
: getAttributes
const { tr } = state
const captureGroup = match[match.length - 1]
const fullMatch = match[0]

View File

@ -1,13 +1,15 @@
import { InputRule } from 'prosemirror-inputrules'
import { NodeType } from 'prosemirror-model'
export default function (regexp: RegExp, type: NodeType, getAttrs?: (match: any) => any): InputRule {
export default function (regexp: RegExp, type: NodeType, getAttributes?: (match: any) => any): InputRule {
return new InputRule(regexp, (state, match, start, end) => {
const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs
const attributes = getAttributes instanceof Function
? getAttributes(match)
: getAttributes
const { tr } = state
if (match[0]) {
tr.replaceWith(start - 1, end, type.create(attrs))
tr.replaceWith(start - 1, end, type.create(attributes))
}
return tr

View File

@ -4,11 +4,11 @@ import { wrappingInputRule } from 'prosemirror-inputrules'
export const inputRegex = /^\s*([-+*])\s$/
const BulletList = createNode({
name: 'bullet_list',
name: 'bulletList',
group: 'block list',
content: 'list_item+',
content: 'listItem+',
parseHTML() {
return [
@ -23,7 +23,7 @@ const BulletList = createNode({
addCommands() {
return {
bulletList: (): Command => ({ commands }) => {
return commands.toggleList('bullet_list', 'list_item')
return commands.toggleList('bulletList', 'listItem')
},
}
},

View File

@ -1,5 +1,5 @@
import { Command, createNode } from '@tiptap/core'
import { chainCommands, exitCode } from 'prosemirror-commands'
import { exitCode } from 'prosemirror-commands'
const HardBreak = createNode({
name: 'hardBreak',
@ -22,19 +22,17 @@ const HardBreak = createNode({
addCommands() {
return {
hardBreak: (): Command => ({ state, dispatch, view }) => {
return chainCommands(
exitCode,
(_, d) => {
if (typeof d !== 'function') {
return false
hardBreak: (): Command => ({ commands, state, dispatch }) => {
return commands.try([
() => exitCode(state, dispatch),
() => {
if (dispatch) {
state.tr.replaceSelectionWith(this.type.create()).scrollIntoView()
}
d(state.tr.replaceSelectionWith(this.type.create()).scrollIntoView())
return true
},
)(state, dispatch, view)
])
},
}
},

View File

@ -1,7 +1,7 @@
import { createNode } from '@tiptap/core'
const ListItem = createNode({
name: 'list_item',
name: 'listItem',
content: '(paragraph|list?)+',
@ -21,9 +21,9 @@ const ListItem = createNode({
addKeyboardShortcuts() {
return {
Enter: () => this.editor.splitListItem('list_item'),
Tab: () => this.editor.sinkListItem('list_item'),
'Shift-Tab': () => this.editor.liftListItem('list_item'),
Enter: () => this.editor.splitListItem('listItem'),
Tab: () => this.editor.sinkListItem('listItem'),
'Shift-Tab': () => this.editor.liftListItem('listItem'),
}
},
})

View File

@ -4,11 +4,11 @@ import { wrappingInputRule } from 'prosemirror-inputrules'
export const inputRegex = /^(\d+)\.\s$/
const OrderedList = createNode({
name: 'ordered_list',
name: 'orderedList',
group: 'block list',
content: 'list_item+',
content: 'listItem+',
addAttributes() {
return {
@ -42,7 +42,7 @@ const OrderedList = createNode({
addCommands() {
return {
orderedList: (): Command => ({ commands }) => {
return commands.toggleList('ordered_list', 'list_item')
return commands.toggleList('orderedList', 'listItem')
},
}
},

View File

@ -8,7 +8,7 @@ export interface TaskItemOptions {
}
const TaskItem = createNode({
name: 'task_item',
name: 'taskItem',
content() {
return this.options.nested ? '(paragraph|task_list)+' : 'paragraph+'
@ -37,20 +37,20 @@ const TaskItem = createNode({
parseHTML() {
return [
{
tag: 'li[data-type="task_item"]',
tag: 'li[data-type="taskItem"]',
priority: 51,
},
]
},
renderHTML({ attributes }) {
return ['li', mergeAttributes(attributes, { 'data-type': 'task_item' }), 0]
return ['li', mergeAttributes(attributes, { 'data-type': 'taskItem' }), 0]
},
addKeyboardShortcuts() {
const shortcuts = {
Enter: () => this.editor.splitListItem('task_item'),
'Shift-Tab': () => this.editor.liftListItem('task_item'),
Enter: () => this.editor.splitListItem('taskItem'),
'Shift-Tab': () => this.editor.liftListItem('taskItem'),
}
if (!this.options.nested) {
@ -59,7 +59,7 @@ const TaskItem = createNode({
return {
...shortcuts,
Tab: () => this.editor.sinkListItem('task_item'),
Tab: () => this.editor.sinkListItem('taskItem'),
}
},

View File

@ -5,7 +5,7 @@ const TaskList = createNode({
group: 'block list',
content: 'task_item+',
content: 'taskItem+',
parseHTML() {
return [
@ -23,7 +23,7 @@ const TaskList = createNode({
addCommands() {
return {
taskList: (): Command => ({ commands }) => {
return commands.toggleList('task_list', 'task_item')
return commands.toggleList('task_list', 'taskItem')
},
}
},

View File

@ -49,7 +49,9 @@ const TextAlign = createExtension({
// TODO: re-use only 'textAlign' attribute
// TODO: use custom splitBlock only for `this.options.types`
// TODO: use complete default enter handler (chainCommand) with custom splitBlock
Enter: () => this.editor.splitBlock(true),
Enter: () => this.editor.splitBlock({
withAttributes: true,
}),
}
},
})

252
yarn.lock
View File

@ -9,10 +9,10 @@
dependencies:
"@babel/highlight" "^7.10.4"
"@babel/compat-data@^7.12.1":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.1.tgz#d7386a689aa0ddf06255005b4b991988021101a0"
integrity sha512-725AQupWJZ8ba0jbKceeFblZTY90McUBWMwHhkFQ9q1zKPJ95GUktljFcgcsIVwRnTnRKlcYzfiNImg5G9m6ZQ==
"@babel/compat-data@^7.12.1", "@babel/compat-data@^7.12.5":
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.5.tgz#f56db0c4bb1bbbf221b4e81345aab4141e7cb0e9"
integrity sha512-DTsS7cxrsH3by8nqQSpFSyjSfSYl57D6Cf4q8dW3LK83tBKBDCkfcay1nYkXq1nIHXnpX8WMMb/O25HOy3h1zg==
"@babel/core@^7.0.0", "@babel/core@^7.10.2", "@babel/core@^7.11.0", "@babel/core@^7.11.6":
version "7.12.3"
@ -36,12 +36,12 @@
semver "^5.4.1"
source-map "^0.5.0"
"@babel/generator@^7.12.1":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.1.tgz#0d70be32bdaa03d7c51c8597dda76e0df1f15468"
integrity sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==
"@babel/generator@^7.12.1", "@babel/generator@^7.12.5":
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de"
integrity sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A==
dependencies:
"@babel/types" "^7.12.1"
"@babel/types" "^7.12.5"
jsesc "^2.5.1"
source-map "^0.5.0"
@ -78,13 +78,13 @@
"@babel/types" "^7.10.4"
"@babel/helper-compilation-targets@^7.12.1", "@babel/helper-compilation-targets@^7.9.6":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.1.tgz#310e352888fbdbdd8577be8dfdd2afb9e7adcf50"
integrity sha512-jtBEif7jsPwP27GPHs06v4WBV0KrE8a/P7n0N0sSvHn2hwUCYnolP/CLmz51IzAW4NlN+HuoBtb9QcwnRo9F/g==
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831"
integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw==
dependencies:
"@babel/compat-data" "^7.12.1"
"@babel/compat-data" "^7.12.5"
"@babel/helper-validator-option" "^7.12.1"
browserslist "^4.12.0"
browserslist "^4.14.5"
semver "^5.5.0"
"@babel/helper-create-class-features-plugin@^7.12.1", "@babel/helper-create-class-features-plugin@^7.7.4":
@ -154,11 +154,11 @@
"@babel/types" "^7.12.1"
"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.8.3":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz#1644c01591a15a2f084dd6d092d9430eb1d1216c"
integrity sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA==
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb"
integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==
dependencies:
"@babel/types" "^7.12.1"
"@babel/types" "^7.12.5"
"@babel/helper-module-transforms@^7.12.1":
version "7.12.1"
@ -204,14 +204,14 @@
"@babel/types" "^7.12.1"
"@babel/helper-replace-supers@^7.12.1":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz#f15c9cc897439281891e11d5ce12562ac0cf3fa9"
integrity sha512-zJjTvtNJnCFsCXVi5rUInstLd/EIVNmIKA1Q9ynESmMBWPWd+7sdR+G4/wdu+Mppfep0XLyG2m7EBPvjCeFyrw==
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz#f009a17543bbbbce16b06206ae73b63d3fca68d9"
integrity sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA==
dependencies:
"@babel/helper-member-expression-to-functions" "^7.12.1"
"@babel/helper-optimise-call-expression" "^7.10.4"
"@babel/traverse" "^7.12.1"
"@babel/types" "^7.12.1"
"@babel/traverse" "^7.12.5"
"@babel/types" "^7.12.5"
"@babel/helper-simple-access@^7.12.1":
version "7.12.1"
@ -255,13 +255,13 @@
"@babel/types" "^7.10.4"
"@babel/helpers@^7.12.1":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.1.tgz#8a8261c1d438ec18cb890434df4ec768734c1e79"
integrity sha512-9JoDSBGoWtmbay98efmT2+mySkwjzeFeAL9BuWNoVQpkPFQF8SIIFUfY5os9u8wVzglzoiPRSW7cuJmBDUt43g==
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e"
integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==
dependencies:
"@babel/template" "^7.10.4"
"@babel/traverse" "^7.12.1"
"@babel/types" "^7.12.1"
"@babel/traverse" "^7.12.5"
"@babel/types" "^7.12.5"
"@babel/highlight@^7.10.4":
version "7.10.4"
@ -272,10 +272,10 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
"@babel/parser@^7.0.0", "@babel/parser@^7.10.4", "@babel/parser@^7.12.0", "@babel/parser@^7.12.1", "@babel/parser@^7.12.3", "@babel/parser@^7.3.3":
version "7.12.3"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.3.tgz#a305415ebe7a6c7023b40b5122a0662d928334cd"
integrity sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==
"@babel/parser@^7.0.0", "@babel/parser@^7.10.4", "@babel/parser@^7.12.0", "@babel/parser@^7.12.3", "@babel/parser@^7.12.5", "@babel/parser@^7.3.3":
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.5.tgz#b4af32ddd473c0bfa643bd7ff0728b8e71b81ea0"
integrity sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==
"@babel/plugin-proposal-async-generator-functions@^7.12.1":
version "7.12.1"
@ -352,9 +352,9 @@
"@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0"
"@babel/plugin-proposal-numeric-separator@^7.12.1":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.1.tgz#0e2c6774c4ce48be412119b4d693ac777f7685a6"
integrity sha512-MR7Ok+Af3OhNTCxYVjJZHS0t97ydnJZt/DbR4WISO39iDnhiD8XHrY12xuSJ90FFEGjir0Fzyyn7g/zY6hxbxA==
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.5.tgz#b1ce757156d40ed79d59d467cb2b154a5c4149ba"
integrity sha512-UiAnkKuOrCyjZ3sYNHlRlfuZJbBHknMQ9VMwVeX97Ofwx7RpD6gS2HfqTCh8KNUQgcOm8IKt103oR4KIjh7Q8g==
dependencies:
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-syntax-numeric-separator" "^7.10.4"
@ -712,10 +712,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-transform-react-jsx-development@^7.12.1":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.1.tgz#0b8f8cd531dcf7991f1e5f2c10a2a4f1cfc78e36"
integrity sha512-IilcGWdN1yNgEGOrB96jbTplRh+V2Pz1EoEwsKsHfX1a/L40cUYuD71Zepa7C+ujv7kJIxnDftWeZbKNEqZjCQ==
"@babel/plugin-transform-react-jsx-development@^7.12.5":
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.5.tgz#677de5b96da310430d6cfb7fee16a1603afa3d56"
integrity sha512-1JJusg3iPgsZDthyWiCr3KQiGs31ikU/mSf2N2dSYEAO0GEImmVUbWf0VoSDGDFTAn5Dj4DUiR6SdIXHY7tELA==
dependencies:
"@babel/helper-builder-react-jsx-experimental" "^7.12.1"
"@babel/helper-plugin-utils" "^7.10.4"
@ -735,10 +735,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-transform-react-jsx@^7.10.1", "@babel/plugin-transform-react-jsx@^7.12.1":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.1.tgz#c2d96c77c2b0e4362cc4e77a43ce7c2539d478cb"
integrity sha512-RmKejwnT0T0QzQUzcbP5p1VWlpnP8QHtdhEtLG55ZDQnJNalbF3eeDyu3dnGKvGzFIQiBzFhBYTwvv435p9Xpw==
"@babel/plugin-transform-react-jsx@^7.10.1", "@babel/plugin-transform-react-jsx@^7.12.5":
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.5.tgz#39ede0e30159770561b6963be143e40af3bde00c"
integrity sha512-2xkcPqqrYiOQgSlM/iwto1paPijjsDbUynN13tI6bosDz/jOW3CRzYguIE8wKX32h+msbBM22Dv5fwrFkUOZjQ==
dependencies:
"@babel/helper-builder-react-jsx" "^7.10.4"
"@babel/helper-builder-react-jsx-experimental" "^7.12.1"
@ -921,22 +921,22 @@
esutils "^2.0.2"
"@babel/preset-react@^7.10.4":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.1.tgz#7f022b13f55b6dd82f00f16d1c599ae62985358c"
integrity sha512-euCExymHCi0qB9u5fKw7rvlw7AZSjw/NaB9h7EkdTt5+yHRrXdiRTh7fkG3uBPpJg82CqLfp1LHLqWGSCrab+g==
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.5.tgz#d45625f65d53612078a43867c5c6750e78772c56"
integrity sha512-jcs++VPrgyFehkMezHtezS2BpnUlR7tQFAyesJn1vGTO9aTFZrgIQrA5YydlTwxbcjMwkFY6i04flCigRRr3GA==
dependencies:
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-transform-react-display-name" "^7.12.1"
"@babel/plugin-transform-react-jsx" "^7.12.1"
"@babel/plugin-transform-react-jsx-development" "^7.12.1"
"@babel/plugin-transform-react-jsx" "^7.12.5"
"@babel/plugin-transform-react-jsx-development" "^7.12.5"
"@babel/plugin-transform-react-jsx-self" "^7.12.1"
"@babel/plugin-transform-react-jsx-source" "^7.12.1"
"@babel/plugin-transform-react-pure-annotations" "^7.12.1"
"@babel/runtime@^7.11.0", "@babel/runtime@^7.11.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.1.tgz#b4116a6b6711d010b2dad3b7b6e43bf1b9954740"
integrity sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA==
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e"
integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==
dependencies:
regenerator-runtime "^0.13.4"
@ -949,25 +949,25 @@
"@babel/parser" "^7.10.4"
"@babel/types" "^7.10.4"
"@babel/traverse@^7.0.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.1.tgz#941395e0c5cc86d5d3e75caa095d3924526f0c1e"
integrity sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==
"@babel/traverse@^7.0.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5":
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.5.tgz#78a0c68c8e8a35e4cacfd31db8bb303d5606f095"
integrity sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/generator" "^7.12.1"
"@babel/generator" "^7.12.5"
"@babel/helper-function-name" "^7.10.4"
"@babel/helper-split-export-declaration" "^7.11.0"
"@babel/parser" "^7.12.1"
"@babel/types" "^7.12.1"
"@babel/parser" "^7.12.5"
"@babel/types" "^7.12.5"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.19"
"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.0", "@babel/types@^7.12.1", "@babel/types@^7.4.4":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.1.tgz#e109d9ab99a8de735be287ee3d6a9947a190c4ae"
integrity sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==
"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.4.4":
version "7.12.6"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.6.tgz#ae0e55ef1cce1fbc881cd26f8234eb3e657edc96"
integrity sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA==
dependencies:
"@babel/helper-validator-identifier" "^7.10.4"
lodash "^4.17.19"
@ -2411,60 +2411,60 @@
"@types/vfile-message" "*"
"@typescript-eslint/eslint-plugin@^4.6.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.6.0.tgz#210cd538bb703f883aff81d3996961f5dba31fdb"
integrity sha512-1+419X+Ynijytr1iWI+/IcX/kJryc78YNpdaXR1aRO1sU3bC0vZrIAF1tIX7rudVI84W7o7M4zo5p1aVt70fAg==
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.6.1.tgz#99d77eb7a016fd5a5e749d2c44a7e4c317eb7da3"
integrity sha512-SNZyflefTMK2JyrPfFFzzoy2asLmZvZJ6+/L5cIqg4HfKGiW2Gr1Go1OyEVqne/U4QwmoasuMwppoBHWBWF2nA==
dependencies:
"@typescript-eslint/experimental-utils" "4.6.0"
"@typescript-eslint/scope-manager" "4.6.0"
"@typescript-eslint/experimental-utils" "4.6.1"
"@typescript-eslint/scope-manager" "4.6.1"
debug "^4.1.1"
functional-red-black-tree "^1.0.1"
regexpp "^3.0.0"
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/experimental-utils@4.6.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.6.0.tgz#f750aef4dd8e5970b5c36084f0a5ca2f0db309a4"
integrity sha512-pnh6Beh2/4xjJVNL+keP49DFHk3orDHHFylSp3WEjtgW3y1U+6l+jNnJrGlbs6qhAz5z96aFmmbUyKhunXKvKw==
"@typescript-eslint/experimental-utils@4.6.1":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.6.1.tgz#a9c691dfd530a9570274fe68907c24c07a06c4aa"
integrity sha512-qyPqCFWlHZXkEBoV56UxHSoXW2qnTr4JrWVXOh3soBP3q0o7p4pUEMfInDwIa0dB/ypdtm7gLOS0hg0a73ijfg==
dependencies:
"@types/json-schema" "^7.0.3"
"@typescript-eslint/scope-manager" "4.6.0"
"@typescript-eslint/types" "4.6.0"
"@typescript-eslint/typescript-estree" "4.6.0"
"@typescript-eslint/scope-manager" "4.6.1"
"@typescript-eslint/types" "4.6.1"
"@typescript-eslint/typescript-estree" "4.6.1"
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
"@typescript-eslint/parser@^4.6.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.6.0.tgz#7e9ff7df2f21d5c8f65f17add3b99eeeec33199d"
integrity sha512-Dj6NJxBhbdbPSZ5DYsQqpR32MwujF772F2H3VojWU6iT4AqL4BKuoNWOPFCoSZvCcADDvQjDpa6OLDAaiZPz2Q==
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.6.1.tgz#b801bff67b536ecc4a840ac9289ba2be57e02428"
integrity sha512-lScKRPt1wM9UwyKkGKyQDqf0bh6jm8DQ5iN37urRIXDm16GEv+HGEmum2Fc423xlk5NUOkOpfTnKZc/tqKZkDQ==
dependencies:
"@typescript-eslint/scope-manager" "4.6.0"
"@typescript-eslint/types" "4.6.0"
"@typescript-eslint/typescript-estree" "4.6.0"
"@typescript-eslint/scope-manager" "4.6.1"
"@typescript-eslint/types" "4.6.1"
"@typescript-eslint/typescript-estree" "4.6.1"
debug "^4.1.1"
"@typescript-eslint/scope-manager@4.6.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.6.0.tgz#b7d8b57fe354047a72dfb31881d9643092838662"
integrity sha512-uZx5KvStXP/lwrMrfQQwDNvh2ppiXzz5TmyTVHb+5TfZ3sUP7U1onlz3pjoWrK9konRyFe1czyxObWTly27Ang==
"@typescript-eslint/scope-manager@4.6.1":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.6.1.tgz#21872b91cbf7adfc7083f17b8041149148baf992"
integrity sha512-f95+80r6VdINYscJY1KDUEDcxZ3prAWHulL4qRDfNVD0I5QAVSGqFkwHERDoLYJJWmEAkUMdQVvx7/c2Hp+Bjg==
dependencies:
"@typescript-eslint/types" "4.6.0"
"@typescript-eslint/visitor-keys" "4.6.0"
"@typescript-eslint/types" "4.6.1"
"@typescript-eslint/visitor-keys" "4.6.1"
"@typescript-eslint/types@4.6.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.6.0.tgz#157ca925637fd53c193c6bf226a6c02b752dde2f"
integrity sha512-5FAgjqH68SfFG4UTtIFv+rqYJg0nLjfkjD0iv+5O27a0xEeNZ5rZNDvFGZDizlCD1Ifj7MAbSW2DPMrf0E9zjA==
"@typescript-eslint/types@4.6.1":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.6.1.tgz#d3ad7478f53f22e7339dc006ab61aac131231552"
integrity sha512-k2ZCHhJ96YZyPIsykickez+OMHkz06xppVLfJ+DY90i532/Cx2Z+HiRMH8YZQo7a4zVd/TwNBuRCdXlGK4yo8w==
"@typescript-eslint/typescript-estree@4.6.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.6.0.tgz#85bd98dcc8280511cfc5b2ce7b03a9ffa1732b08"
integrity sha512-s4Z9qubMrAo/tw0CbN0IN4AtfwuehGXVZM0CHNMdfYMGBDhPdwTEpBrecwhP7dRJu6d9tT9ECYNaWDHvlFSngA==
"@typescript-eslint/typescript-estree@4.6.1":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.6.1.tgz#6025cce724329413f57e4959b2d676fceeca246f"
integrity sha512-/J/kxiyjQQKqEr5kuKLNQ1Finpfb8gf/NpbwqFFYEBjxOsZ621r9AqwS9UDRA1Rrr/eneX/YsbPAIhU2rFLjXQ==
dependencies:
"@typescript-eslint/types" "4.6.0"
"@typescript-eslint/visitor-keys" "4.6.0"
"@typescript-eslint/types" "4.6.1"
"@typescript-eslint/visitor-keys" "4.6.1"
debug "^4.1.1"
globby "^11.0.1"
is-glob "^4.0.1"
@ -2472,12 +2472,12 @@
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/visitor-keys@4.6.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.6.0.tgz#fb05d6393891b0a089b243fc8f9fb8039383d5da"
integrity sha512-38Aa9Ztl0XyFPVzmutHXqDMCu15Xx8yKvUo38Gu3GhsuckCh3StPI5t2WIO9LHEsOH7MLmlGfKUisU8eW1Sjhg==
"@typescript-eslint/visitor-keys@4.6.1":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.6.1.tgz#6b125883402d8939df7b54528d879e88f7ba3614"
integrity sha512-owABze4toX7QXwOLT3/D5a8NecZEjEWU1srqxENTfqsY3bwVnl3YYbOh6s1rp2wQKO9RTHFGjKes08FgE7SVMw==
dependencies:
"@typescript-eslint/types" "4.6.0"
"@typescript-eslint/types" "4.6.1"
eslint-visitor-keys "^2.0.0"
"@vue/babel-helper-vue-jsx-merge-props@^1.2.1":
@ -3588,7 +3588,7 @@ browserify-zlib@^0.2.0:
dependencies:
pako "~1.0.5"
browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.8.5:
browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.8.5:
version "4.14.6"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.6.tgz#97702a9c212e0c6b6afefad913d3a1538e348457"
integrity sha512-zeFYcUo85ENhc/zxHbiIp0LGzzTrE2Pv2JhxvS7kpUb9Q9D38kUX6Bie7pGutJ/5iF5rOxE7CepAuWD56xJ33A==
@ -5428,9 +5428,9 @@ ee-first@1.1.1:
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
electron-to-chromium@^1.3.585:
version "1.3.585"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.585.tgz#71cdb722c73488b9475ad1c572cf43a763ef9081"
integrity sha512-xoeqjMQhgHDZM7FiglJAb2aeOxHZWFruUc3MbAGTgE7GB8rr5fTn1Sdh5THGuQtndU3GuXlu91ZKqRivxoCZ/A==
version "1.3.588"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.588.tgz#c6515571737bfb42678115a5eaa818384593a9a5"
integrity sha512-0zr+ZfytnLeJZxGgmEpPTcItu5Mm4A5zHPZXLfHcGp0mdsk95rmD7ePNewYtK1yIdLbk8Z1U2oTRRfOtR4gbYg==
elegant-spinner@^1.0.1:
version "1.0.1"
@ -7897,9 +7897,9 @@ is-buffer@^1.1.5:
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-buffer@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623"
integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==
version "2.0.5"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191"
integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==
is-callable@^1.1.4, is-callable@^1.2.2:
version "1.2.2"
@ -7926,9 +7926,9 @@ is-color-stop@^1.0.0:
rgba-regex "^1.0.0"
is-core-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.0.0.tgz#58531b70aed1db7c0e8d4eb1a0a2d1ddd64bd12d"
integrity sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw==
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946"
integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==
dependencies:
has "^1.0.3"
@ -9018,9 +9018,9 @@ markdown-escapes@^1.0.0:
integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==
marked@^1.1.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.2.tgz#5d77ffb789c4cb0ae828bfe76250f7140b123f70"
integrity sha512-5jjKHVl/FPo0Z6ocP3zYhKiJLzkwJAw4CZoLjv57FkvbUuwOX4LIBBGGcXjAY6ATcd1q9B8UTj5T9Umauj0QYQ==
version "1.2.3"
resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.3.tgz#58817ba348a7c9398cb94d40d12e0d08df83af57"
integrity sha512-RQuL2i6I6Gn+9n81IDNGbL0VHnta4a+8ZhqvryXEniTb/hQNtf3i26hi1XWUhzb9BgVyWHKR3UO8MaHtKoYibw==
maxmin@^2.1.0:
version "2.1.0"
@ -13608,9 +13608,9 @@ trough@^1.0.0:
glob "^7.1.2"
ts-loader@^8.0.7:
version "8.0.7"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.7.tgz#9ce70db5b3906cc9143a09c54ff5247d102ea974"
integrity sha512-ooa4wxlZ9TOXaJ/iVyZlWsim79Ul4KyifSwyT2hOrbQA6NZJypsLOE198o8Ko+JV+ZHnMArvWcl4AnRqpCU/Mw==
version "8.0.9"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.9.tgz#890fc25f49a99124268f4e738ed22d00f666dc37"
integrity sha512-rQd+iIfz5z4HSVzhhRFP4M2OQ0QmihilWWauYvvowBfnRvr4DW+gqA2om70xp/07EQj1qBkLMWobnXsgmWMbmg==
dependencies:
chalk "^2.3.0"
enhanced-resolve "^4.0.0"
@ -13750,9 +13750,9 @@ uglify-js@3.4.x:
source-map "~0.6.1"
uglify-js@^3.1.4:
version "3.11.4"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.11.4.tgz#b47b7ae99d4bd1dca65b53aaa69caa0909e6fadf"
integrity sha512-FyYnoxVL1D6+jDGQpbK5jW6y/2JlVfRfEeQ67BPCUg5wfCjaKOpr2XeceE4QL+MkhxliLtf5EbrMDZgzpt2CNw==
version "3.11.5"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.11.5.tgz#d6788bc83cf35ff18ea78a65763e480803409bc6"
integrity sha512-btvv/baMqe7HxP7zJSF7Uc16h1mSfuuSplT0/qdjxseesDU+yYzH33eHBH+eMdeRXwujXspaCTooWHQVVBh09w==
uid-number@0.0.6:
version "0.0.6"
@ -13871,9 +13871,9 @@ unist-builder@^1.0.1, unist-builder@^1.0.3, unist-builder@^1.0.4:
object-assign "^4.1.0"
unist-util-generated@^1.1.0:
version "1.1.5"
resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.5.tgz#1e903e68467931ebfaea386dae9ea253628acd42"
integrity sha512-1TC+NxQa4N9pNdayCYA1EGUOCAO0Le3fVp7Jzns6lnua/mYgwHo0tz5WUAfrdpNch1RZLHc61VZ1SDgrtNXLSw==
version "1.1.6"
resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b"
integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==
unist-util-is@^2.0.0:
version "2.1.3"
@ -14818,8 +14818,8 @@ yauzl@^2.10.0, yauzl@^2.4.2:
fd-slicer "~1.1.0"
yjs@^13.4.1:
version "13.4.2"
resolved "https://registry.yarnpkg.com/yjs/-/yjs-13.4.2.tgz#565fff706064e6fe59b75cc08dd724b2ac4f3783"
integrity sha512-HtlrDT55db2Gtu09UDijDCCH+7FLG2FX+TRP0ySZJZYPj22qkinS2oAcuzjKbsJ1Ed0RSJGSgUE6ImagFdMJvA==
version "13.4.3"
resolved "https://registry.yarnpkg.com/yjs/-/yjs-13.4.3.tgz#b10c63cbc4e6fd1bc3a7974965b75fefc72f70c3"
integrity sha512-jHlk3SKz2gC/rO0WBEuyn8yxtxEjDDMuANQYLR7EJjdbYhbdKYiaoPsNsFOgMDy7u8R6i2N3gVIRcmXYrbAvzg==
dependencies:
lib0 "^0.2.33"