Merge branch 'master' into feature/suggestions

# Conflicts:
#	packages/tiptap-extensions/package.json
This commit is contained in:
Philipp Kühn
2018-09-04 23:12:00 +02:00
24 changed files with 1045 additions and 652 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "tiptap-extensions",
"version": "0.6.1",
"version": "0.8.0",
"description": "Extensions for tiptap",
"homepage": "https://tiptap.scrumpy.io",
"license": "MIT",
@@ -20,10 +20,11 @@
"url": "https://github.com/heyscrumpy/tiptap/issues"
},
"dependencies": {
"lowlight": "^1.10.0",
"prosemirror-history": "^1.0.2",
"prosemirror-state": "^1.2.2",
"prosemirror-view": "^1.5.1",
"tiptap": "^0.8.0",
"tiptap-commands": "^0.2.4"
"tiptap": "^0.10.0",
"tiptap-commands": "^0.3.0"
}
}

View File

@@ -1,6 +1,7 @@
export { default as BlockquoteNode } from './nodes/Blockquote'
export { default as BulletListNode } from './nodes/BulletList'
export { default as CodeBlockNode } from './nodes/CodeBlock'
export { default as CodeBlockHighlightNode } from './nodes/CodeBlockHighlight'
export { default as HardBreakNode } from './nodes/HardBreak'
export { default as HeadingNode } from './nodes/Heading'
export { default as ImageNode } from './nodes/Image'

View File

@@ -1,5 +1,5 @@
import { Node } from 'tiptap'
import { wrappingInputRule, setBlockType, wrapIn } from 'tiptap-commands'
import { Node, Plugin } from 'tiptap'
import { wrappingInputRule, wrapIn } from 'tiptap-commands'
export default class BlockquoteNode extends Node {

View File

@@ -0,0 +1,126 @@
import { Node, Plugin } from 'tiptap'
import { Decoration, DecorationSet } from 'prosemirror-view'
import { toggleBlockType, setBlockType, textblockTypeInputRule } from 'tiptap-commands'
import { findBlockNodes } from 'prosemirror-utils'
import low from 'lowlight'
function getDecorations(doc) {
const decorations = []
const blocks = findBlockNodes(doc)
.filter(item => item.node.type.name === 'code_block')
const flatten = list => list.reduce(
(a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), [],
)
function parseNodes(nodes, className = []) {
return nodes.map(node => {
const classes = [
...className,
...node.properties ? node.properties.className : [],
]
if (node.children) {
return parseNodes(node.children, classes)
}
return {
text: node.value,
classes,
}
})
}
blocks.forEach(block => {
let startPos = block.pos + 1
const nodes = low.highlightAuto(block.node.textContent).value
flatten(parseNodes(nodes))
.map(node => {
const from = startPos
const to = from + node.text.length
startPos = to
return {
...node,
from,
to,
}
})
.forEach(node => {
const decoration = Decoration.inline(node.from, node.to, {
class: node.classes.join(' '),
})
decorations.push(decoration)
})
})
return DecorationSet.create(doc, decorations)
}
export default class CodeBlockHighlightNode extends Node {
get name() {
return 'code_block'
}
get schema() {
return {
content: 'text*',
marks: '',
group: 'block',
code: true,
defining: true,
draggable: false,
parseDOM: [
{ tag: 'pre', preserveWhitespace: 'full' },
],
toDOM: () => ['pre', ['code', 0]],
}
}
command({ type, schema }) {
return toggleBlockType(type, schema.nodes.paragraph)
}
keys({ type }) {
return {
'Shift-Ctrl-\\': setBlockType(type),
}
}
inputRules({ type }) {
return [
textblockTypeInputRule(/^```$/, type),
]
}
get plugins() {
return [
new Plugin({
state: {
init(_, { doc }) {
return getDecorations(doc)
},
apply(tr, set) {
// TODO: find way to cache decorations
// see: https://discuss.prosemirror.net/t/how-to-update-multiple-inline-decorations-on-node-change/1493
if (tr.docChanged) {
return getDecorations(tr.doc)
}
return set.map(tr.mapping, tr.doc)
},
},
props: {
decorations(state) {
return this.getState(state)
},
},
}),
]
}
}

View File

@@ -1,5 +1,5 @@
import { Node } from 'tiptap'
import { splitListItem, liftListItem } from 'tiptap-commands'
import { splitToDefaultListItem, liftListItem } from 'tiptap-commands'
export default class TodoItemNode extends Node {
@@ -58,7 +58,7 @@ export default class TodoItemNode extends Node {
keys({ type }) {
return {
Enter: splitListItem(type),
Enter: splitToDefaultListItem(type),
'Shift-Tab': liftListItem(type),
}
}