prosemirror-commands
Advanced tools
Comparing version 0.14.0 to 0.15.0
@@ -16,11 +16,3 @@ var ref = require("prosemirror-transform"); | ||
var extendTransformAction = ref$2.extendTransformAction; | ||
var ref$3 = require("extending-char"); | ||
var isExtendingCharAt = ref$3.isExtendingCharAt; | ||
var ref$4 = require("./platform"); | ||
var ios = ref$4.ios; | ||
var mac = ref$4.mac; | ||
var ref$5 = require("./char"); | ||
var charCategory = ref$5.charCategory; | ||
// :: (EditorState, ?(action: Action)) → bool | ||
@@ -35,3 +27,3 @@ // Delete the selection, if there is one. | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// :: (EditorState, ?(action: Action), ?EditorView) → bool | ||
// If the selection is empty and at the start of a textblock, move | ||
@@ -41,8 +33,11 @@ // that block closer to the block before it, by lifting it out of its | ||
// before it, moving it into a parent of that node, or joining it with | ||
// that. | ||
function joinBackward(state, onAction) { | ||
// that. Will use the view for accurate start-of-textblock detection | ||
// if given. | ||
function joinBackward(state, onAction, view) { | ||
var ref = state.selection; | ||
var $head = ref.$head; | ||
var empty = ref.empty; | ||
if (!empty || $head.parentOffset > 0) { return false } | ||
if (!empty || (view ? !view.endOfTextblock("backward", state) | ||
: $head.parentOffset > 0)) | ||
{ return false } | ||
@@ -59,12 +54,5 @@ // Find the node before this one | ||
var range = $head.blockRange(), target = range && liftTarget(range) | ||
if (target != null) { | ||
if (onAction) { onAction(state.tr.lift(range, target).scrollAction()) } | ||
return true | ||
} else if ($head.depth == 1 && !$head.parent.content.size) { | ||
// Else, if the cursor is in an empty textblock, delete it | ||
if (onAction) { onAction(state.tr.delete($head.before(1), $head.after(1)).scrollAction()) } | ||
return true | ||
} else { | ||
return false | ||
} | ||
if (target == null) { return false } | ||
if (onAction) { onAction(state.tr.lift(range, target).scrollAction()) } | ||
return true | ||
} | ||
@@ -94,3 +82,3 @@ | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// :: (EditorState, ?(action: Action), ?EditorView) → bool | ||
// If the selection is empty and the cursor is at the end of a | ||
@@ -100,8 +88,11 @@ // textblock, move the node after it closer to the node with the | ||
// into parents of the cursor block, or joining the two when they are | ||
// siblings). | ||
function joinForward(state, onAction) { | ||
// siblings). Will use the view for accurate start-of-textblock | ||
// detection if given. | ||
function joinForward(state, onAction, view) { | ||
var ref = state.selection; | ||
var $head = ref.$head; | ||
var empty = ref.empty; | ||
if (!empty || $head.parentOffset < $head.parent.content.size) { return false } | ||
if (!empty || (view ? !view.endOfTextblock("forward", state) | ||
: $head.parentOffset < $head.parent.content.size)) | ||
{ return false } | ||
@@ -118,12 +109,4 @@ // Find the node after this one | ||
// There is no node after this | ||
if (!after) { | ||
// If the cursor is in an empty block, delete that block | ||
if ($head.depth == 1 && !$head.parent.content.size) { | ||
if (onAction) { onAction(state.tr.delete($head.before(1), $head.after(1)).scrollAction()) } | ||
return true | ||
} else { | ||
return false | ||
} | ||
} | ||
// If there is no node after this, there's nothing to do | ||
if (!after) { return false } | ||
@@ -141,60 +124,2 @@ // If the node doesn't allow children, delete it | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// Delete the character before the cursor, if the selection is empty | ||
// and the cursor isn't at the start of a textblock. | ||
function deleteCharBefore(state, onAction) { | ||
var ref = state.selection; | ||
var $head = ref.$head; | ||
var empty = ref.empty; | ||
if (!empty || $head.parentOffset == 0) { return false } | ||
if (onAction) { | ||
var dest = moveBackward($head, "char") | ||
onAction(state.tr.delete(dest, $head.pos).scrollAction()) | ||
} | ||
return true | ||
} | ||
exports.deleteCharBefore = deleteCharBefore | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// Delete the word before the cursor, if the selection is empty and | ||
// the cursor isn't at the start of a textblock. | ||
function deleteWordBefore(state, onAction) { | ||
var ref = state.selection; | ||
var $head = ref.$head; | ||
var empty = ref.empty; | ||
if (!empty || $head.parentOffset == 0) { return false } | ||
if (onAction) | ||
{ onAction(state.tr.delete(moveBackward($head, "word"), $head.pos).scrollAction()) } | ||
return true | ||
} | ||
exports.deleteWordBefore = deleteWordBefore | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// Delete the character after the cursor, if the selection is empty | ||
// and the cursor isn't at the end of its textblock. | ||
function deleteCharAfter(state, onAction) { | ||
var ref = state.selection; | ||
var $head = ref.$head; | ||
var empty = ref.empty; | ||
if (!empty || $head.parentOffset == $head.parent.content.size) { return false } | ||
if (onAction) | ||
{ onAction(state.tr.delete($head.pos, moveForward($head, "char")).scrollAction()) } | ||
return true | ||
} | ||
exports.deleteCharAfter = deleteCharAfter | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// Delete the word after the cursor, if the selection is empty and the | ||
// cursor isn't at the end of a textblock. | ||
function deleteWordAfter(state, onAction) { | ||
var ref = state.selection; | ||
var $head = ref.$head; | ||
var empty = ref.empty; | ||
if (!empty || $head.parentOffset == $head.parent.content.size) { return false } | ||
if (onAction) | ||
{ onAction(state.tr.delete($head.pos, moveForward($head, "word")).scrollAction()) } | ||
return true | ||
} | ||
exports.deleteWordAfter = deleteWordAfter | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// Join the selected block or, if there is a text selection, the | ||
@@ -260,7 +185,5 @@ // closest ancestor block of the selection that can be joined, with | ||
var ref = state.selection; | ||
var $from = ref.$from; | ||
var $to = ref.$to; | ||
var node = ref.node; | ||
if (node) { return false } | ||
if (!$from.parent.type.spec.code || $to.pos >= $from.end()) { return false } | ||
var $head = ref.$head; | ||
var anchor = ref.anchor; | ||
if (!$head || !$head.parent.type.spec.code || $head.sharedDepth(anchor) != $head.depth) { return false } | ||
if (onAction) { onAction(state.tr.insertText("\n").scrollAction()) } | ||
@@ -272,2 +195,22 @@ return true | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// When the selection is in a node with a truthy | ||
// [`code`](#model.NodeSpec.code) property in its spec, create a | ||
// default block after the code block, and move the cursor there. | ||
function exitCode(state, onAction) { | ||
var ref = state.selection; | ||
var $head = ref.$head; | ||
var anchor = ref.anchor; | ||
if (!$head || !$head.parent.type.spec.code || $head.sharedDepth(anchor) != $head.depth) { return false } | ||
var above = $head.node(-1), after = $head.indexAfter(-1), type = above.defaultContentType(after) | ||
if (!above.canReplaceWith(after, after, type)) { return false } | ||
if (onAction) { | ||
var pos = $head.after(), tr = state.tr.replaceWith(pos, pos, type.createAndFill()) | ||
tr.setSelection(Selection.near(tr.doc.resolve(pos), 1)) | ||
onAction(tr.scrollAction()) | ||
} | ||
return true | ||
} | ||
exports.exitCode = exitCode | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// If a block node is selected, create an empty paragraph before (if | ||
@@ -369,12 +312,21 @@ // it is its parent's first child) or after it. | ||
function joinMaybeClear(state, $pos, onAction) { | ||
var before = $pos.nodeBefore, after = $pos.nodeAfter, index = $pos.index() | ||
if (!before || !after || !before.type.compatibleContent(after.type)) { return false } | ||
if (!before.content.size && $pos.parent.canReplace(index - 1, index)) { | ||
if (onAction) { onAction(state.tr.delete($pos.pos - before.nodeSize, $pos.pos).scrollAction()) } | ||
return true | ||
} | ||
if (!$pos.parent.canReplace(index, index + 1)) { return false } | ||
if (onAction) | ||
{ onAction(state.tr | ||
.clearNonMatching($pos.pos, before.contentMatchAt(before.childCount)) | ||
.join($pos.pos) | ||
.scrollAction()) } | ||
return true | ||
} | ||
function deleteBarrier(state, cut, onAction) { | ||
var $cut = state.doc.resolve(cut), before = $cut.nodeBefore, after = $cut.nodeAfter, conn, match | ||
if (canJoin(state.doc, cut)) { | ||
if (onAction) { | ||
var tr = state.tr.join(cut) | ||
if (tr.steps.length && before.content.size == 0 && !before.sameMarkup(after) && | ||
$cut.parent.canReplace($cut.index() - 1, $cut.index())) | ||
{ tr.setNodeType(cut - before.nodeSize, after.type, after.attrs) } | ||
onAction(tr.scrollAction()) | ||
} | ||
if (joinMaybeClear(state, $cut, onAction)) { | ||
return true | ||
@@ -389,6 +341,6 @@ } else if (after.isTextblock && $cut.parent.canReplace($cut.index(), $cut.index() + 1) && | ||
wrap = Fragment.from(before.copy(wrap)) | ||
var tr$1 = state.tr.step(new ReplaceAroundStep(cut - 1, end, cut, end, new Slice(wrap, 1, 0), conn.length, true)) | ||
var tr = state.tr.step(new ReplaceAroundStep(cut - 1, end, cut, end, new Slice(wrap, 1, 0), conn.length, true)) | ||
var joinAt = end + 2 * conn.length | ||
if (canJoin(tr$1.doc, joinAt)) { tr$1.join(joinAt) } | ||
onAction(tr$1.scrollAction()) | ||
if (canJoin(tr.doc, joinAt)) { tr.join(joinAt) } | ||
onAction(tr.scrollAction()) | ||
} | ||
@@ -410,93 +362,6 @@ return true | ||
if (onAction) | ||
{ onAction(NodeSelection.create(state.doc, cut - (dir > 0 ? 0 : node.nodeSize)).action()) } | ||
{ onAction(NodeSelection.create(state.doc, cut - (dir > 0 ? 0 : node.nodeSize)).scrollAction()) } | ||
return true | ||
} | ||
// :: (ResolvedPos, string) → number | ||
// Get an offset moving backward from a current offset inside a node. If by is "char", it will | ||
// consider one character back. If it is "word" it will work from the current position backwards | ||
// through text of a singular character category (e.g. "cat" of "#!*") until reaching a character | ||
// in a different category (i.e. the beginning of the word). | ||
// Note that this method is at this point unlikely to work reliably for non-European scripts. | ||
function moveBackward($pos, by) { | ||
if (by != "char" && by != "word") | ||
{ throw new RangeError("Unknown motion unit: " + by) } | ||
var parent = $pos.parent, offset = $pos.parentOffset | ||
var cat = null, counted = 0, pos = $pos.pos | ||
for (;;) { | ||
if (offset == 0) { return pos } | ||
var ref = parent.childBefore(offset); | ||
var start = ref.offset; | ||
var node = ref.node; | ||
if (!node) { return pos } | ||
if (!node.isText) { return cat ? pos : pos - 1 } | ||
if (by == "char") { | ||
for (var i = offset - start; i > 0; i--) { | ||
if (!isExtendingCharAt(node.text, i - 1)) | ||
{ return pos - 1 } | ||
offset-- | ||
pos-- | ||
} | ||
} else if (by == "word") { | ||
// Work from the current position backwards through text of a singular | ||
// character category (e.g. "cat" of "#!*") until reaching a character in a | ||
// different category (i.e. the end of the word). | ||
for (var i$1 = offset - start; i$1 > 0; i$1--) { | ||
var nextCharCat = charCategory(node.text.charAt(i$1 - 1)) | ||
if (cat == null || counted == 1 && cat == "space") { cat = nextCharCat } | ||
else if (cat != nextCharCat) { return pos } | ||
offset-- | ||
pos-- | ||
counted++ | ||
} | ||
} | ||
} | ||
} | ||
exports.moveBackward = moveBackward | ||
// :: (ResolvedPos, string) → number | ||
// Get an offset moving forward from a current offset inside a node. If by is "char", it will | ||
// consider one character forward. If it is "word" it will work from the current position forward | ||
// through text of a singular character category (e.g. "cat" of "#!*") until reaching a character | ||
// in a different category (i.e. the end of the word). | ||
// Note that this method is at this point unlikely to work reliably for non-European scripts. | ||
function moveForward($pos, by) { | ||
if (by != "char" && by != "word") | ||
{ throw new RangeError("Unknown motion unit: " + by) } | ||
var parent = $pos.parent, offset = $pos.parentOffset, pos = $pos.pos | ||
var cat = null, counted = 0 | ||
for (;;) { | ||
if (offset == parent.content.size) { return pos } | ||
var ref = parent.childAfter(offset); | ||
var start = ref.offset; | ||
var node = ref.node; | ||
if (!node) { return pos } | ||
if (!node.isText) { return cat ? pos : pos + 1 } | ||
if (by == "char") { | ||
for (var i = offset - start; i < node.text.length; i++) { | ||
if (!isExtendingCharAt(node.text, i + 1)) | ||
{ return pos + 1 } | ||
offset++ | ||
pos++ | ||
} | ||
} else if (by == "word") { | ||
for (var i$1 = offset - start; i$1 < node.text.length; i$1++) { | ||
var nextCharCat = charCategory(node.text.charAt(i$1)) | ||
if (cat == null || counted == 1 && cat == "space") { cat = nextCharCat } | ||
else if (cat != nextCharCat) { return pos } | ||
offset++ | ||
pos++ | ||
counted++ | ||
} | ||
} | ||
} | ||
} | ||
exports.moveForward = moveForward | ||
// Parameterized commands | ||
@@ -551,3 +416,3 @@ | ||
onAction(state.tr | ||
.clearMarkupFor(where, nodeType, attrs) | ||
.clearNonMatching(where, nodeType.contentExpr.start(attrs)) | ||
.setNodeType(where, nodeType, attrs) | ||
@@ -662,5 +527,5 @@ .scrollAction()) | ||
return function(state, onAction) { | ||
return function(state, onAction, view) { | ||
for (var i = 0; i < commands.length; i++) | ||
{ if (commands[i](state, onAction)) { return true } } | ||
{ if (commands[i](state, onAction, view)) { return true } } | ||
return false | ||
@@ -677,6 +542,7 @@ } | ||
// * **Enter** to `newlineInCode`, `createParagraphNear`, `liftEmptyBlock`, `splitBlock` | ||
// * **Backspace** to `deleteSelection`, `joinBackward`, `deleteCharBefore` | ||
// * **Mod-Backspace** to `deleteSelection`, `joinBackward`, `deleteWordBefore` | ||
// * **Delete** to `deleteSelection`, `joinForward`, `deleteCharAfter` | ||
// * **Mod-Delete** to `deleteSelection`, `joinForward`, `deleteWordAfter` | ||
// * **Mod-Enter** to `exitCode` | ||
// * **Backspace** to `deleteSelection`, `joinBackward` | ||
// * **Mod-Backspace** to `deleteSelection`, `joinBackward` | ||
// * **Delete** to `deleteSelection`, `joinForward` | ||
// * **Mod-Delete** to `deleteSelection`, `joinForward` | ||
// * **Alt-ArrowUp** to `joinUp` | ||
@@ -688,7 +554,8 @@ // * **Alt-ArrowDown** to `joinDown` | ||
"Enter": chainCommands(newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock), | ||
"Mod-Enter": exitCode, | ||
"Backspace": ios ? chainCommands(deleteSelection, joinBackward) : chainCommands(deleteSelection, joinBackward, deleteCharBefore), | ||
"Mod-Backspace": chainCommands(deleteSelection, joinBackward, deleteWordBefore), | ||
"Delete": chainCommands(deleteSelection, joinForward, deleteCharAfter), | ||
"Mod-Delete": chainCommands(deleteSelection, joinForward, deleteWordAfter), | ||
"Backspace": chainCommands(deleteSelection, joinBackward), | ||
"Mod-Backspace": chainCommands(deleteSelection, joinBackward), | ||
"Delete": chainCommands(deleteSelection, joinForward), | ||
"Mod-Delete": chainCommands(deleteSelection, joinForward), | ||
@@ -701,2 +568,6 @@ "Alt-ArrowUp": joinUp, | ||
// declare global: os, navigator | ||
var mac = typeof navigator != "undefined" ? /Mac/.test(navigator.platform) | ||
: typeof os != "undefined" ? os.platform() == "darwin" : false | ||
if (mac) { | ||
@@ -703,0 +574,0 @@ var extra = { |
{ | ||
"name": "prosemirror-commands", | ||
"version": "0.14.0", | ||
"version": "0.15.0", | ||
"description": "Editing commands for ProseMirror", | ||
@@ -19,6 +19,5 @@ "main": "dist/commands.js", | ||
"dependencies": { | ||
"prosemirror-model": "^0.14.0", | ||
"prosemirror-transform": "^0.14.0", | ||
"prosemirror-state": "^0.14.0", | ||
"extending-char": "^1.0.0" | ||
"prosemirror-model": "^0.15.0", | ||
"prosemirror-transform": "^0.15.0", | ||
"prosemirror-state": "^0.15.0" | ||
}, | ||
@@ -34,5 +33,4 @@ "devDependencies": { | ||
"build": "rimraf dist && buble -i src -o dist", | ||
"link-src": "rimraf dist && ln -s src dist", | ||
"prepublish": "npm run build" | ||
} | ||
} |
const {joinPoint, canJoin, findWrapping, liftTarget, canSplit, ReplaceAroundStep} = require("prosemirror-transform") | ||
const {Slice, Fragment} = require("prosemirror-model") | ||
const {Selection, TextSelection, NodeSelection, extendTransformAction} = require("prosemirror-state") | ||
const {isExtendingCharAt} = require("extending-char") | ||
const {ios, mac} = require("./platform") | ||
const {charCategory} = require("./char") | ||
// :: (EditorState, ?(action: Action)) → bool | ||
@@ -18,3 +14,3 @@ // Delete the selection, if there is one. | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// :: (EditorState, ?(action: Action), ?EditorView) → bool | ||
// If the selection is empty and at the start of a textblock, move | ||
@@ -24,6 +20,9 @@ // that block closer to the block before it, by lifting it out of its | ||
// before it, moving it into a parent of that node, or joining it with | ||
// that. | ||
function joinBackward(state, onAction) { | ||
// that. Will use the view for accurate start-of-textblock detection | ||
// if given. | ||
function joinBackward(state, onAction, view) { | ||
let {$head, empty} = state.selection | ||
if (!empty || $head.parentOffset > 0) return false | ||
if (!empty || (view ? !view.endOfTextblock("backward", state) | ||
: $head.parentOffset > 0)) | ||
return false | ||
@@ -40,12 +39,5 @@ // Find the node before this one | ||
let range = $head.blockRange(), target = range && liftTarget(range) | ||
if (target != null) { | ||
if (onAction) onAction(state.tr.lift(range, target).scrollAction()) | ||
return true | ||
} else if ($head.depth == 1 && !$head.parent.content.size) { | ||
// Else, if the cursor is in an empty textblock, delete it | ||
if (onAction) onAction(state.tr.delete($head.before(1), $head.after(1)).scrollAction()) | ||
return true | ||
} else { | ||
return false | ||
} | ||
if (target == null) return false | ||
if (onAction) onAction(state.tr.lift(range, target).scrollAction()) | ||
return true | ||
} | ||
@@ -75,3 +67,3 @@ | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// :: (EditorState, ?(action: Action), ?EditorView) → bool | ||
// If the selection is empty and the cursor is at the end of a | ||
@@ -81,6 +73,9 @@ // textblock, move the node after it closer to the node with the | ||
// into parents of the cursor block, or joining the two when they are | ||
// siblings). | ||
function joinForward(state, onAction) { | ||
// siblings). Will use the view for accurate start-of-textblock | ||
// detection if given. | ||
function joinForward(state, onAction, view) { | ||
let {$head, empty} = state.selection | ||
if (!empty || $head.parentOffset < $head.parent.content.size) return false | ||
if (!empty || (view ? !view.endOfTextblock("forward", state) | ||
: $head.parentOffset < $head.parent.content.size)) | ||
return false | ||
@@ -97,12 +92,4 @@ // Find the node after this one | ||
// There is no node after this | ||
if (!after) { | ||
// If the cursor is in an empty block, delete that block | ||
if ($head.depth == 1 && !$head.parent.content.size) { | ||
if (onAction) onAction(state.tr.delete($head.before(1), $head.after(1)).scrollAction()) | ||
return true | ||
} else { | ||
return false | ||
} | ||
} | ||
// If there is no node after this, there's nothing to do | ||
if (!after) return false | ||
@@ -120,52 +107,2 @@ // If the node doesn't allow children, delete it | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// Delete the character before the cursor, if the selection is empty | ||
// and the cursor isn't at the start of a textblock. | ||
function deleteCharBefore(state, onAction) { | ||
let {$head, empty} = state.selection | ||
if (!empty || $head.parentOffset == 0) return false | ||
if (onAction) { | ||
let dest = moveBackward($head, "char") | ||
onAction(state.tr.delete(dest, $head.pos).scrollAction()) | ||
} | ||
return true | ||
} | ||
exports.deleteCharBefore = deleteCharBefore | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// Delete the word before the cursor, if the selection is empty and | ||
// the cursor isn't at the start of a textblock. | ||
function deleteWordBefore(state, onAction) { | ||
let {$head, empty} = state.selection | ||
if (!empty || $head.parentOffset == 0) return false | ||
if (onAction) | ||
onAction(state.tr.delete(moveBackward($head, "word"), $head.pos).scrollAction()) | ||
return true | ||
} | ||
exports.deleteWordBefore = deleteWordBefore | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// Delete the character after the cursor, if the selection is empty | ||
// and the cursor isn't at the end of its textblock. | ||
function deleteCharAfter(state, onAction) { | ||
let {$head, empty} = state.selection | ||
if (!empty || $head.parentOffset == $head.parent.content.size) return false | ||
if (onAction) | ||
onAction(state.tr.delete($head.pos, moveForward($head, "char")).scrollAction()) | ||
return true | ||
} | ||
exports.deleteCharAfter = deleteCharAfter | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// Delete the word after the cursor, if the selection is empty and the | ||
// cursor isn't at the end of a textblock. | ||
function deleteWordAfter(state, onAction) { | ||
let {$head, empty} = state.selection | ||
if (!empty || $head.parentOffset == $head.parent.content.size) return false | ||
if (onAction) | ||
onAction(state.tr.delete($head.pos, moveForward($head, "word")).scrollAction()) | ||
return true | ||
} | ||
exports.deleteWordAfter = deleteWordAfter | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// Join the selected block or, if there is a text selection, the | ||
@@ -225,5 +162,4 @@ // closest ancestor block of the selection that can be joined, with | ||
function newlineInCode(state, onAction) { | ||
let {$from, $to, node} = state.selection | ||
if (node) return false | ||
if (!$from.parent.type.spec.code || $to.pos >= $from.end()) return false | ||
let {$head, anchor} = state.selection | ||
if (!$head || !$head.parent.type.spec.code || $head.sharedDepth(anchor) != $head.depth) return false | ||
if (onAction) onAction(state.tr.insertText("\n").scrollAction()) | ||
@@ -235,2 +171,20 @@ return true | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// When the selection is in a node with a truthy | ||
// [`code`](#model.NodeSpec.code) property in its spec, create a | ||
// default block after the code block, and move the cursor there. | ||
function exitCode(state, onAction) { | ||
let {$head, anchor} = state.selection | ||
if (!$head || !$head.parent.type.spec.code || $head.sharedDepth(anchor) != $head.depth) return false | ||
let above = $head.node(-1), after = $head.indexAfter(-1), type = above.defaultContentType(after) | ||
if (!above.canReplaceWith(after, after, type)) return false | ||
if (onAction) { | ||
let pos = $head.after(), tr = state.tr.replaceWith(pos, pos, type.createAndFill()) | ||
tr.setSelection(Selection.near(tr.doc.resolve(pos), 1)) | ||
onAction(tr.scrollAction()) | ||
} | ||
return true | ||
} | ||
exports.exitCode = exitCode | ||
// :: (EditorState, ?(action: Action)) → bool | ||
// If a block node is selected, create an empty paragraph before (if | ||
@@ -324,12 +278,21 @@ // it is its parent's first child) or after it. | ||
function joinMaybeClear(state, $pos, onAction) { | ||
let before = $pos.nodeBefore, after = $pos.nodeAfter, index = $pos.index() | ||
if (!before || !after || !before.type.compatibleContent(after.type)) return false | ||
if (!before.content.size && $pos.parent.canReplace(index - 1, index)) { | ||
if (onAction) onAction(state.tr.delete($pos.pos - before.nodeSize, $pos.pos).scrollAction()) | ||
return true | ||
} | ||
if (!$pos.parent.canReplace(index, index + 1)) return false | ||
if (onAction) | ||
onAction(state.tr | ||
.clearNonMatching($pos.pos, before.contentMatchAt(before.childCount)) | ||
.join($pos.pos) | ||
.scrollAction()) | ||
return true | ||
} | ||
function deleteBarrier(state, cut, onAction) { | ||
let $cut = state.doc.resolve(cut), before = $cut.nodeBefore, after = $cut.nodeAfter, conn, match | ||
if (canJoin(state.doc, cut)) { | ||
if (onAction) { | ||
let tr = state.tr.join(cut) | ||
if (tr.steps.length && before.content.size == 0 && !before.sameMarkup(after) && | ||
$cut.parent.canReplace($cut.index() - 1, $cut.index())) | ||
tr.setNodeType(cut - before.nodeSize, after.type, after.attrs) | ||
onAction(tr.scrollAction()) | ||
} | ||
if (joinMaybeClear(state, $cut, onAction)) { | ||
return true | ||
@@ -364,89 +327,6 @@ } else if (after.isTextblock && $cut.parent.canReplace($cut.index(), $cut.index() + 1) && | ||
if (onAction) | ||
onAction(NodeSelection.create(state.doc, cut - (dir > 0 ? 0 : node.nodeSize)).action()) | ||
onAction(NodeSelection.create(state.doc, cut - (dir > 0 ? 0 : node.nodeSize)).scrollAction()) | ||
return true | ||
} | ||
// :: (ResolvedPos, string) → number | ||
// Get an offset moving backward from a current offset inside a node. If by is "char", it will | ||
// consider one character back. If it is "word" it will work from the current position backwards | ||
// through text of a singular character category (e.g. "cat" of "#!*") until reaching a character | ||
// in a different category (i.e. the beginning of the word). | ||
// Note that this method is at this point unlikely to work reliably for non-European scripts. | ||
function moveBackward($pos, by) { | ||
if (by != "char" && by != "word") | ||
throw new RangeError("Unknown motion unit: " + by) | ||
let parent = $pos.parent, offset = $pos.parentOffset | ||
let cat = null, counted = 0, pos = $pos.pos | ||
for (;;) { | ||
if (offset == 0) return pos | ||
let {offset: start, node} = parent.childBefore(offset) | ||
if (!node) return pos | ||
if (!node.isText) return cat ? pos : pos - 1 | ||
if (by == "char") { | ||
for (let i = offset - start; i > 0; i--) { | ||
if (!isExtendingCharAt(node.text, i - 1)) | ||
return pos - 1 | ||
offset-- | ||
pos-- | ||
} | ||
} else if (by == "word") { | ||
// Work from the current position backwards through text of a singular | ||
// character category (e.g. "cat" of "#!*") until reaching a character in a | ||
// different category (i.e. the end of the word). | ||
for (let i = offset - start; i > 0; i--) { | ||
let nextCharCat = charCategory(node.text.charAt(i - 1)) | ||
if (cat == null || counted == 1 && cat == "space") cat = nextCharCat | ||
else if (cat != nextCharCat) return pos | ||
offset-- | ||
pos-- | ||
counted++ | ||
} | ||
} | ||
} | ||
} | ||
exports.moveBackward = moveBackward | ||
// :: (ResolvedPos, string) → number | ||
// Get an offset moving forward from a current offset inside a node. If by is "char", it will | ||
// consider one character forward. If it is "word" it will work from the current position forward | ||
// through text of a singular character category (e.g. "cat" of "#!*") until reaching a character | ||
// in a different category (i.e. the end of the word). | ||
// Note that this method is at this point unlikely to work reliably for non-European scripts. | ||
function moveForward($pos, by) { | ||
if (by != "char" && by != "word") | ||
throw new RangeError("Unknown motion unit: " + by) | ||
let parent = $pos.parent, offset = $pos.parentOffset, pos = $pos.pos | ||
let cat = null, counted = 0 | ||
for (;;) { | ||
if (offset == parent.content.size) return pos | ||
let {offset: start, node} = parent.childAfter(offset) | ||
if (!node) return pos | ||
if (!node.isText) return cat ? pos : pos + 1 | ||
if (by == "char") { | ||
for (let i = offset - start; i < node.text.length; i++) { | ||
if (!isExtendingCharAt(node.text, i + 1)) | ||
return pos + 1 | ||
offset++ | ||
pos++ | ||
} | ||
} else if (by == "word") { | ||
for (let i = offset - start; i < node.text.length; i++) { | ||
let nextCharCat = charCategory(node.text.charAt(i)) | ||
if (cat == null || counted == 1 && cat == "space") cat = nextCharCat | ||
else if (cat != nextCharCat) return pos | ||
offset++ | ||
pos++ | ||
counted++ | ||
} | ||
} | ||
} | ||
} | ||
exports.moveForward = moveForward | ||
// Parameterized commands | ||
@@ -493,3 +373,3 @@ | ||
onAction(state.tr | ||
.clearMarkupFor(where, nodeType, attrs) | ||
.clearNonMatching(where, nodeType.contentExpr.start(attrs)) | ||
.setNodeType(where, nodeType, attrs) | ||
@@ -598,5 +478,5 @@ .scrollAction()) | ||
function chainCommands(...commands) { | ||
return function(state, onAction) { | ||
return function(state, onAction, view) { | ||
for (let i = 0; i < commands.length; i++) | ||
if (commands[i](state, onAction)) return true | ||
if (commands[i](state, onAction, view)) return true | ||
return false | ||
@@ -613,6 +493,7 @@ } | ||
// * **Enter** to `newlineInCode`, `createParagraphNear`, `liftEmptyBlock`, `splitBlock` | ||
// * **Backspace** to `deleteSelection`, `joinBackward`, `deleteCharBefore` | ||
// * **Mod-Backspace** to `deleteSelection`, `joinBackward`, `deleteWordBefore` | ||
// * **Delete** to `deleteSelection`, `joinForward`, `deleteCharAfter` | ||
// * **Mod-Delete** to `deleteSelection`, `joinForward`, `deleteWordAfter` | ||
// * **Mod-Enter** to `exitCode` | ||
// * **Backspace** to `deleteSelection`, `joinBackward` | ||
// * **Mod-Backspace** to `deleteSelection`, `joinBackward` | ||
// * **Delete** to `deleteSelection`, `joinForward` | ||
// * **Mod-Delete** to `deleteSelection`, `joinForward` | ||
// * **Alt-ArrowUp** to `joinUp` | ||
@@ -624,7 +505,8 @@ // * **Alt-ArrowDown** to `joinDown` | ||
"Enter": chainCommands(newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock), | ||
"Mod-Enter": exitCode, | ||
"Backspace": ios ? chainCommands(deleteSelection, joinBackward) : chainCommands(deleteSelection, joinBackward, deleteCharBefore), | ||
"Mod-Backspace": chainCommands(deleteSelection, joinBackward, deleteWordBefore), | ||
"Delete": chainCommands(deleteSelection, joinForward, deleteCharAfter), | ||
"Mod-Delete": chainCommands(deleteSelection, joinForward, deleteWordAfter), | ||
"Backspace": chainCommands(deleteSelection, joinBackward), | ||
"Mod-Backspace": chainCommands(deleteSelection, joinBackward), | ||
"Delete": chainCommands(deleteSelection, joinForward), | ||
"Mod-Delete": chainCommands(deleteSelection, joinForward), | ||
@@ -637,2 +519,6 @@ "Alt-ArrowUp": joinUp, | ||
// declare global: os, navigator | ||
const mac = typeof navigator != "undefined" ? /Mac/.test(navigator.platform) | ||
: typeof os != "undefined" ? os.platform() == "darwin" : false | ||
if (mac) { | ||
@@ -639,0 +525,0 @@ let extra = { |
@@ -15,8 +15,2 @@ This module exports a number of ‘commands‘, which are building block | ||
@joinForward | ||
@deleteCharBefore | ||
@deleteWordBefore | ||
@deleteCharAfter | ||
@deleteWordAfter | ||
@moveBackward | ||
@moveForward | ||
@joinUp | ||
@@ -26,2 +20,3 @@ @joinDown | ||
@newlineInCode | ||
@exitCode | ||
@createParagraphNear | ||
@@ -28,0 +23,0 @@ @liftEmptyBlock |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3
49504
9
1006
+ Addedprosemirror-model@0.15.0(transitive)
+ Addedprosemirror-state@0.15.0(transitive)
+ Addedprosemirror-transform@0.15.0(transitive)
- Removedextending-char@^1.0.0
- Removedextending-char@1.0.1(transitive)
- Removedprosemirror-model@0.14.1(transitive)
- Removedprosemirror-state@0.14.0(transitive)
- Removedprosemirror-transform@0.14.0(transitive)
Updatedprosemirror-model@^0.15.0
Updatedprosemirror-state@^0.15.0