Socket
Socket
Sign inDemoInstall

prosemirror-state

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

prosemirror-state - npm Package Compare versions

Comparing version 0.18.0 to 0.19.0

16

dist/plugin.js

@@ -51,4 +51,2 @@ // PluginSpec:: Object

var warnedAboutOptions = false
// ::- Plugins wrap extra functionality that can be added to an

@@ -74,17 +72,5 @@ // editor. They can define new [state fields](#state.StateField), and

var prototypeAccessors = { options: {} };
prototypeAccessors.options.get = function () {
if (!warnedAboutOptions && typeof "console" != "undefined" && console.warn) {
warnedAboutOptions = true
console.warn("Plugin.options was renamed to Plugin.spec")
}
return this.spec
};
// :: (EditorState) → any
// Get the state field for this plugin.
Plugin.prototype.getState = function getState (state) { return state[this.key] };
Object.defineProperties( Plugin.prototype, prototypeAccessors );
exports.Plugin = Plugin

@@ -102,3 +88,3 @@

// that `instance` is a half-initialized state instance, and will
// not have values for any fields initialzed after this one.
// not have values for any fields initialized after this one.
//

@@ -105,0 +91,0 @@ // apply:: (tr: Transaction, value: T, oldState: EditorState, newState: EditorState) → T

231

dist/selection.js

@@ -0,16 +1,45 @@

var warnedAboutBetween = false
var classesById = Object.create(null)
// ::- Superclass for editor selections.
var Selection = function Selection($from, $to) {
var Selection = function Selection($anchor, $head) {
if ( $head === void 0 ) $head = $anchor;
// :: ResolvedPos
// The resolved lower bound of the selection
this.$from = $from
// The resolved anchor of the selection (the side that stays in
// place when the selection is modified).
this.$anchor = $anchor
// :: ResolvedPos
// The resolved upper bound of the selection
this.$to = $to
// The resolved head of the selection (the side that moves when
// the selection is modified).
this.$head = $head
};
var prototypeAccessors = { from: {},to: {},empty: {} };
var prototypeAccessors = { anchor: {},head: {},$from: {},$to: {},from: {},to: {},empty: {} };
// :: bool
// True if the selection is an empty text selection (head an anchor
// are the same).
// :: number
// The selection's immobile side (does not move when
// shift-selecting).
prototypeAccessors.anchor.get = function () { return this.$anchor.pos };
// :: number
// The selection's mobile side (the side that moves when
// shift-selecting).
prototypeAccessors.head.get = function () { return this.$head.pos };
// :: ResolvedPos
// The resolved lower bound of the selection.
prototypeAccessors.$from.get = function () {
return this.$head.pos < this.$anchor.pos ? this.$head : this.$anchor
};
// :: ResolvedPos
// The resolved upper bound of the selection.
prototypeAccessors.$to.get = function () {
return this.$head.pos < this.$anchor.pos ? this.$anchor : this.$head
};
// :: number
// The lower bound of the selection.
prototypeAccessors.from.get = function () { return this.$from.pos };

@@ -22,8 +51,15 @@

// :: bool
// True if the selection is empty (head and anchor are the same).
prototypeAccessors.empty.get = function () {
return this.from == this.to
return this.head == this.anchor
};
// eq:: (other: Selection) → bool
// Test whether the selection is the same as another selection.
// eq:: (Selection) → bool
// Test whether the selection is the same as another selection. The
// default implementation tests whether they have the same class,
// head, and anchor.
Selection.prototype.eq = function eq (other) {
return other instanceof this.constructor && other.anchor == this.anchor && other.head == this.head
};

@@ -35,3 +71,10 @@ // map:: (doc: Node, mapping: Mappable) → Selection

// toJSON:: () → Object
// Convert the selection to a JSON representation.
// Convert the selection to a JSON representation. When implementing
// this for a custom selection class, make sure to give the object a
// `type` property whose value matches the ID under which you
// [registered](#state.Selection^jsonID) your class. The default
// implementation adds `type`, `head`, and `anchor` properties.
Selection.prototype.toJSON = function toJSON () {
return {type: this.jsonID, anchor: this.anchor, head: this.head}
};

@@ -44,3 +87,3 @@ // :: (ResolvedPos, number, ?bool) → ?Selection

Selection.findFrom = function findFrom ($pos, dir, textOnly) {
var inner = $pos.parent.isTextblock ? new TextSelection($pos)
var inner = $pos.parent.inlineContent ? new TextSelection($pos)
: findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly)

@@ -86,52 +129,59 @@ if (inner) { return inner }

// :: (ResolvedPos, ResolvedPos, ?number) → Selection
// Find a selection that spans the given positions, if both are text
// positions. If not, return some other selection nearby, where
// `bias` determines whether the method searches forward (default)
// or backwards (negative number) first.
Selection.between = function between ($anchor, $head, bias) {
var found = Selection.near($head, bias)
if (found instanceof TextSelection) {
var nearAnchor = Selection.findFrom($anchor, $anchor.pos > found.to ? -1 : 1, true)
found = new TextSelection(nearAnchor.$anchor, found.$head)
} else if ($anchor.pos < found.from || $anchor.pos > found.to) {
// If head falls on a node, but anchor falls outside of it, create
// a text selection between them
var inv = $anchor.pos > found.to
var foundAnchor = Selection.findFrom($anchor, inv ? -1 : 1, true)
var foundHead = Selection.findFrom(inv ? found.$from : found.$to, inv ? 1 : -1, true)
if (foundAnchor && foundHead)
{ found = new TextSelection(foundAnchor.$anchor, foundHead.$head) }
if (!warnedAboutBetween && typeof console != "undefined" && console.warn) {
warnedAboutBetween = true
console.warn("Selection.between is now called TextSelection.between")
}
return found
return TextSelection.between($anchor, $head, bias)
};
// : (Object, Mapping) → Object
// Map a JSON object representing this selection through a mapping.
Selection.mapJSON = function mapJSON (json, mapping) {
if (json.anchor != null)
{ return {head: mapping.map(json.head), anchor: mapping.map(json.anchor)} }
else
{ return {node: mapping.map(json.node), after: mapping.map(json.after, -1)} }
var result = {}
for (var prop in json) {
var value = json[prop]
if (prop == "anchor" || prop == "head")
{ value = mapping.map(value, json.type == "node" && prop == "head" ? -1 : 1) }
result[prop] = value
}
return result
};
// :: (Node, Object) → Selection
// Deserialize a JSON representation of a selection.
// Deserialize a JSON representation of a selection. Must be
// implemented for custom classes (as a static class method).
Selection.fromJSON = function fromJSON (doc, json) {
// This is cautious, because the history will blindly map
// selections and then try to deserialize them, and the endpoints
// might not point at appropriate positions anymore (though they
// are guaranteed to be inside of the document's range).
if (json.head != null) {
var $anchor = doc.resolve(json.anchor), $head = doc.resolve(json.head)
if ($anchor.parent.isTextblock && $head.parent.isTextblock) { return new TextSelection($anchor, $head) }
else { return Selection.between($anchor, $head) }
} else {
var $pos = doc.resolve(json.node), after = $pos.nodeAfter
if (after && json.after == json.pos + after.nodeSize && NodeSelection.isSelectable(after)) { return new NodeSelection($pos) }
else { return Selection.near($pos) }
}
var cls = classesById[json.type]
if (!cls) { return this.backwardsCompatFromJSON(doc, json) }
return cls.fromJSON(doc, json)
};
Selection.backwardsCompatFromJSON = function backwardsCompatFromJSON (doc, json) {
if (json.anchor != null) { return TextSelection.fromJSON(doc, json) }
if (json.node != null) { return NodeSelection.fromJSON(doc, {anchor: json.node, head: json.after}) }
throw new RangeError("Unrecognized JSON data " + JSON.stringify(json))
};
// :: (string, constructor<Selection>)
// To be able to deserialize selections from JSON, custom selection
// classes must register themselves with an ID string, so that they
// can be disambiguated. Try to pick something that's unlikely to
// clash with classes from other modules.
Selection.jsonID = function jsonID (id, selectionClass) {
if (id in classesById) { throw new RangeError("Duplicate use of selection JSON ID " + id) }
classesById[id] = selectionClass
selectionClass.prototype.jsonID = id
return selectionClass
};
Object.defineProperties( Selection.prototype, prototypeAccessors );
exports.Selection = Selection
// :: bool
// Controls whether, when a selection of this type is active in the
// browser, the selected range should be visible to the user. Defaults
// to `true`.
Selection.prototype.visible = true
// ::- A text selection represents a classical editor

@@ -142,11 +192,4 @@ // selection, with a head (the moving side) and anchor (immobile

var TextSelection = (function (Selection) {
function TextSelection($anchor, $head) {
if ( $head === void 0 ) $head = $anchor;
var inv = $anchor.pos > $head.pos
Selection.call(this, inv ? $head : $anchor, inv ? $anchor : $head)
// :: ResolvedPos The resolved anchor of the selection.
this.$anchor = $anchor
// :: ResolvedPos The resolved head of the selection.
this.$head = $head
function TextSelection () {
Selection.apply(this, arguments);
}

@@ -158,27 +201,13 @@

var prototypeAccessors$1 = { anchor: {},head: {},inverted: {} };
var prototypeAccessors$1 = { $cursor: {} };
prototypeAccessors$1.anchor.get = function () { return this.$anchor.pos };
// :: number
// The selection's mobile side (the side that moves when pressing
// shift-arrow).
prototypeAccessors$1.head.get = function () { return this.$head.pos };
prototypeAccessors$1.$cursor.get = function () { return this.empty ? this.$head : null };
prototypeAccessors$1.inverted.get = function () { return this.anchor > this.head };
TextSelection.prototype.eq = function eq (other) {
return other instanceof TextSelection && other.head == this.head && other.anchor == this.anchor
};
TextSelection.prototype.map = function map (doc, mapping) {
var $head = doc.resolve(mapping.map(this.head))
if (!$head.parent.isTextblock) { return Selection.near($head) }
if (!$head.parent.inlineContent) { return Selection.near($head) }
var $anchor = doc.resolve(mapping.map(this.anchor))
return new TextSelection($anchor.parent.isTextblock ? $anchor : $head, $head)
return new TextSelection($anchor.parent.inlineContent ? $anchor : $head, $head)
};
TextSelection.prototype.toJSON = function toJSON () {
return {head: this.head, anchor: this.anchor}
};
// :: (Node, number, ?number) → TextSelection

@@ -193,2 +222,26 @@ // Create a text selection from non-resolved positions.

// :: (ResolvedPos, ResolvedPos, ?number) → TextSelection
// Return a text selection that spans the given positions or, if
// they aren't text positions, find a text selection near them.
// `bias` determines whether the method searches forward (default)
// or backwards (negative number) first.
TextSelection.between = function between ($anchor, $head, bias) {
var dir = $anchor.pos > $head.pos ? -1 : 1
if (!$head.parent.inlineContent)
{ $head = Selection.near($head, bias || -dir, true).$head }
if (!$anchor.parent.inlineContent) {
$anchor = Selection.near($anchor, dir, true).$anchor
if (($anchor.pos > $head.pos) != (dir < 0)) { $anchor = $head }
}
return new TextSelection($anchor, $head)
};
TextSelection.fromJSON = function fromJSON (doc, json) {
// This is cautious, because the history will blindly map
// selections and then try to deserialize them, and the endpoints
// might not point at appropriate positions anymore (though they
// are guaranteed to be inside of the document's range).
return TextSelection.between(doc.resolve(json.anchor), doc.resolve(json.head))
};
Object.defineProperties( TextSelection.prototype, prototypeAccessors$1 );

@@ -200,2 +253,4 @@

Selection.jsonID("text", TextSelection)
// ::- A node selection is a selection that points at a

@@ -217,8 +272,4 @@ // single node. All nodes marked [selectable](#model.NodeSpec.selectable)

NodeSelection.prototype.eq = function eq (other) {
return other instanceof NodeSelection && this.from == other.from
};
NodeSelection.prototype.map = function map (doc, mapping) {
var from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1)
var from = mapping.mapResult(this.anchor, 1), to = mapping.mapResult(this.head, -1)
var $from = doc.resolve(from.pos), node = $from.nodeAfter

@@ -230,6 +281,2 @@ if (!from.deleted && !to.deleted && node && to.pos == from.pos + node.nodeSize && NodeSelection.isSelectable(node))

NodeSelection.prototype.toJSON = function toJSON () {
return {node: this.from, after: this.to}
};
// :: (Node, number, ?number) → TextSelection

@@ -248,2 +295,8 @@ // Create a node selection from non-resolved positions.

NodeSelection.fromJSON = function fromJSON (doc, json) {
var $from = doc.resolve(json.anchor), node = $from.nodeAfter
if (node && json.head == json.anchor + node.nodeSize && NodeSelection.isSelectable(node)) { return new NodeSelection($from) }
else { return Selection.near($from) }
};
return NodeSelection;

@@ -253,2 +306,6 @@ }(Selection));

NodeSelection.prototype.visible = false
Selection.jsonID("node", NodeSelection)
// FIXME we'll need some awareness of text direction when scanning for selections

@@ -260,3 +317,3 @@

function findSelectionIn(doc, node, pos, index, dir, text) {
if (node.isTextblock) { return TextSelection.create(doc, pos) }
if (node.inlineContent) { return TextSelection.create(doc, pos) }
for (var i = index - (dir > 0 ? 0 : 1); dir > 0 ? i < node.childCount : i >= 0; i += dir) {

@@ -263,0 +320,0 @@ var child = node.child(i)

@@ -19,3 +19,3 @@ var ref = require("prosemirror-transform");

// metadata properties in a transaction, which are extra pieces of
// informations that client code or plugins can use to describe what a
// information that client code or plugins can use to describe what a
// transacion represents, so that they can update their [own

@@ -85,3 +85,3 @@ // state](##state.StateField) accordingly.

// :: (?[Mark]) → Transaction
// Replace the set of stored marks.
// Set the current stored marks.
Transaction.prototype.setStoredMarks = function setStoredMarks (marks) {

@@ -93,2 +93,12 @@ this.storedMarks = marks

// :: ([Mark]) → Transaction
// Make sure the current stored marks or, if that is null, the marks
// at the selection, match the given set of marks. Does nothing if
// this is already the case.
Transaction.prototype.ensureMarks = function ensureMarks (marks) {
if (!Mark.sameSet(this.storedMarks || this.selection.$from.marks(), marks))
{ this.setStoredMarks(marks.length || this.storedMarks ? marks : null) }
return this
};
// :: bool

@@ -156,3 +166,6 @@ // Whether the stored marks were explicitly set for this transaction.

var to = ref.to;
return this.deleteRange(from, to)
var $from = ref.$from;
this.deleteRange(from, to)
if ($from.parentOffset < $from.parent.content.size) { this.ensureMarks($from.marks(true)) }
return this
};

@@ -216,4 +229,3 @@

Transaction.prototype.addStoredMark = function addStoredMark (mark) {
this.storedMarks = mark.addToSet(this.storedMarks || currentMarks(this.selection))
return this
return this.ensureMarks(mark.addToSet(this.storedMarks || this.selection.$head.marks()))
};

@@ -224,4 +236,3 @@

Transaction.prototype.removeStoredMark = function removeStoredMark (mark) {
this.storedMarks = mark.removeFromSet(this.storedMarks || currentMarks(this.selection))
return this
return this.ensureMarks(mark.removeFromSet(this.storedMarks || this.selection.$head.marks()))
};

@@ -241,5 +252,1 @@

}
function currentMarks(selection) {
return selection.head == null ? Mark.none : selection.$head.marks()
}
{
"name": "prosemirror-state",
"version": "0.18.0",
"version": "0.19.0",
"description": "ProseMirror editor state",

@@ -19,4 +19,4 @@ "main": "dist/index.js",

"dependencies": {
"prosemirror-model": "^0.18.0",
"prosemirror-transform": "^0.18.0"
"prosemirror-model": "^0.19.0",
"prosemirror-transform": "^0.19.0"
},

@@ -23,0 +23,0 @@ "devDependencies": {

@@ -51,4 +51,2 @@ // PluginSpec:: Object

let warnedAboutOptions = false
// ::- Plugins wrap extra functionality that can be added to an

@@ -75,10 +73,2 @@ // editor. They can define new [state fields](#state.StateField), and

get options() {
if (!warnedAboutOptions && typeof "console" != "undefined" && console.warn) {
warnedAboutOptions = true
console.warn("Plugin.options was renamed to Plugin.spec")
}
return this.spec
}
// :: (EditorState) → any

@@ -100,3 +90,3 @@ // Get the state field for this plugin.

// that `instance` is a half-initialized state instance, and will
// not have values for any fields initialzed after this one.
// not have values for any fields initialized after this one.
//

@@ -103,0 +93,0 @@ // apply:: (tr: Transaction, value: T, oldState: EditorState, newState: EditorState) → T

@@ -24,3 +24,3 @@ This module implements the state object of a ProseMirror editor, along

@NodeSelection
c
### Plugin System

@@ -27,0 +27,0 @@

@@ -0,4 +1,41 @@

let warnedAboutBetween = false
const classesById = Object.create(null)
// ::- Superclass for editor selections.
class Selection {
constructor($anchor, $head = $anchor) {
// :: ResolvedPos
// The resolved anchor of the selection (the side that stays in
// place when the selection is modified).
this.$anchor = $anchor
// :: ResolvedPos
// The resolved head of the selection (the side that moves when
// the selection is modified).
this.$head = $head
}
// :: number
// The selection's immobile side (does not move when
// shift-selecting).
get anchor() { return this.$anchor.pos }
// :: number
// The selection's mobile side (the side that moves when
// shift-selecting).
get head() { return this.$head.pos }
// :: ResolvedPos
// The resolved lower bound of the selection.
get $from() {
return this.$head.pos < this.$anchor.pos ? this.$head : this.$anchor
}
// :: ResolvedPos
// The resolved upper bound of the selection.
get $to() {
return this.$head.pos < this.$anchor.pos ? this.$anchor : this.$head
}
// :: number
// The lower bound of the selection.

@@ -11,20 +48,15 @@ get from() { return this.$from.pos }

constructor($from, $to) {
// :: ResolvedPos
// The resolved lower bound of the selection
this.$from = $from
// :: ResolvedPos
// The resolved upper bound of the selection
this.$to = $to
}
// :: bool
// True if the selection is an empty text selection (head an anchor
// are the same).
// True if the selection is empty (head and anchor are the same).
get empty() {
return this.from == this.to
return this.head == this.anchor
}
// eq:: (other: Selection) → bool
// Test whether the selection is the same as another selection.
// eq:: (Selection) → bool
// Test whether the selection is the same as another selection. The
// default implementation tests whether they have the same class,
// head, and anchor.
eq(other) {
return other instanceof this.constructor && other.anchor == this.anchor && other.head == this.head
}

@@ -36,3 +68,10 @@ // map:: (doc: Node, mapping: Mappable) → Selection

// toJSON:: () → Object
// Convert the selection to a JSON representation.
// Convert the selection to a JSON representation. When implementing
// this for a custom selection class, make sure to give the object a
// `type` property whose value matches the ID under which you
// [registered](#state.Selection^jsonID) your class. The default
// implementation adds `type`, `head`, and `anchor` properties.
toJSON() {
return {type: this.jsonID, anchor: this.anchor, head: this.head}
}

@@ -45,3 +84,3 @@ // :: (ResolvedPos, number, ?bool) → ?Selection

static findFrom($pos, dir, textOnly) {
let inner = $pos.parent.isTextblock ? new TextSelection($pos)
let inner = $pos.parent.inlineContent ? new TextSelection($pos)
: findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly)

@@ -84,51 +123,58 @@ if (inner) return inner

// :: (ResolvedPos, ResolvedPos, ?number) → Selection
// Find a selection that spans the given positions, if both are text
// positions. If not, return some other selection nearby, where
// `bias` determines whether the method searches forward (default)
// or backwards (negative number) first.
static between($anchor, $head, bias) {
let found = Selection.near($head, bias)
if (found instanceof TextSelection) {
let nearAnchor = Selection.findFrom($anchor, $anchor.pos > found.to ? -1 : 1, true)
found = new TextSelection(nearAnchor.$anchor, found.$head)
} else if ($anchor.pos < found.from || $anchor.pos > found.to) {
// If head falls on a node, but anchor falls outside of it, create
// a text selection between them
let inv = $anchor.pos > found.to
let foundAnchor = Selection.findFrom($anchor, inv ? -1 : 1, true)
let foundHead = Selection.findFrom(inv ? found.$from : found.$to, inv ? 1 : -1, true)
if (foundAnchor && foundHead)
found = new TextSelection(foundAnchor.$anchor, foundHead.$head)
if (!warnedAboutBetween && typeof console != "undefined" && console.warn) {
warnedAboutBetween = true
console.warn("Selection.between is now called TextSelection.between")
}
return found
return TextSelection.between($anchor, $head, bias)
}
// : (Object, Mapping) → Object
// Map a JSON object representing this selection through a mapping.
static mapJSON(json, mapping) {
if (json.anchor != null)
return {head: mapping.map(json.head), anchor: mapping.map(json.anchor)}
else
return {node: mapping.map(json.node), after: mapping.map(json.after, -1)}
let result = {}
for (let prop in json) {
let value = json[prop]
if (prop == "anchor" || prop == "head")
value = mapping.map(value, json.type == "node" && prop == "head" ? -1 : 1)
result[prop] = value
}
return result
}
// :: (Node, Object) → Selection
// Deserialize a JSON representation of a selection.
// Deserialize a JSON representation of a selection. Must be
// implemented for custom classes (as a static class method).
static fromJSON(doc, json) {
// This is cautious, because the history will blindly map
// selections and then try to deserialize them, and the endpoints
// might not point at appropriate positions anymore (though they
// are guaranteed to be inside of the document's range).
if (json.head != null) {
let $anchor = doc.resolve(json.anchor), $head = doc.resolve(json.head)
if ($anchor.parent.isTextblock && $head.parent.isTextblock) return new TextSelection($anchor, $head)
else return Selection.between($anchor, $head)
} else {
let $pos = doc.resolve(json.node), after = $pos.nodeAfter
if (after && json.after == json.pos + after.nodeSize && NodeSelection.isSelectable(after)) return new NodeSelection($pos)
else return Selection.near($pos)
}
let cls = classesById[json.type]
if (!cls) return this.backwardsCompatFromJSON(doc, json)
return cls.fromJSON(doc, json)
}
static backwardsCompatFromJSON(doc, json) {
if (json.anchor != null) return TextSelection.fromJSON(doc, json)
if (json.node != null) return NodeSelection.fromJSON(doc, {anchor: json.node, head: json.after})
throw new RangeError("Unrecognized JSON data " + JSON.stringify(json))
}
// :: (string, constructor<Selection>)
// To be able to deserialize selections from JSON, custom selection
// classes must register themselves with an ID string, so that they
// can be disambiguated. Try to pick something that's unlikely to
// clash with classes from other modules.
static jsonID(id, selectionClass) {
if (id in classesById) throw new RangeError("Duplicate use of selection JSON ID " + id)
classesById[id] = selectionClass
selectionClass.prototype.jsonID = id
return selectionClass
}
}
exports.Selection = Selection
// :: bool
// Controls whether, when a selection of this type is active in the
// browser, the selected range should be visible to the user. Defaults
// to `true`.
Selection.prototype.visible = true
// ::- A text selection represents a classical editor

@@ -139,39 +185,14 @@ // selection, with a head (the moving side) and anchor (immobile

class TextSelection extends Selection {
// :: number
// The selection's immobile side (does not move when pressing
// shift-arrow).
get anchor() { return this.$anchor.pos }
// :: number
// The selection's mobile side (the side that moves when pressing
// shift-arrow).
get head() { return this.$head.pos }
// :: ?ResolvedPos
// Returns a resolved position if this is a cursor selection (an
// empty text selection), and null otherwise.
get $cursor() { return this.empty ? this.$head : null }
// :: (ResolvedPos, ?ResolvedPos)
// Construct a text selection.
constructor($anchor, $head = $anchor) {
let inv = $anchor.pos > $head.pos
super(inv ? $head : $anchor, inv ? $anchor : $head)
// :: ResolvedPos The resolved anchor of the selection.
this.$anchor = $anchor
// :: ResolvedPos The resolved head of the selection.
this.$head = $head
}
get inverted() { return this.anchor > this.head }
eq(other) {
return other instanceof TextSelection && other.head == this.head && other.anchor == this.anchor
}
map(doc, mapping) {
let $head = doc.resolve(mapping.map(this.head))
if (!$head.parent.isTextblock) return Selection.near($head)
if (!$head.parent.inlineContent) return Selection.near($head)
let $anchor = doc.resolve(mapping.map(this.anchor))
return new TextSelection($anchor.parent.isTextblock ? $anchor : $head, $head)
return new TextSelection($anchor.parent.inlineContent ? $anchor : $head, $head)
}
toJSON() {
return {head: this.head, anchor: this.anchor}
}
// :: (Node, number, ?number) → TextSelection

@@ -183,5 +204,31 @@ // Create a text selection from non-resolved positions.

}
// :: (ResolvedPos, ResolvedPos, ?number) → TextSelection
// Return a text selection that spans the given positions or, if
// they aren't text positions, find a text selection near them.
// `bias` determines whether the method searches forward (default)
// or backwards (negative number) first.
static between($anchor, $head, bias) {
let dir = $anchor.pos > $head.pos ? -1 : 1
if (!$head.parent.inlineContent)
$head = Selection.near($head, bias || -dir, true).$head
if (!$anchor.parent.inlineContent) {
$anchor = Selection.near($anchor, dir, true).$anchor
if (($anchor.pos > $head.pos) != (dir < 0)) $anchor = $head
}
return new TextSelection($anchor, $head)
}
static fromJSON(doc, json) {
// This is cautious, because the history will blindly map
// selections and then try to deserialize them, and the endpoints
// might not point at appropriate positions anymore (though they
// are guaranteed to be inside of the document's range).
return TextSelection.between(doc.resolve(json.anchor), doc.resolve(json.head))
}
}
exports.TextSelection = TextSelection
Selection.jsonID("text", TextSelection)
// ::- A node selection is a selection that points at a

@@ -202,8 +249,4 @@ // single node. All nodes marked [selectable](#model.NodeSpec.selectable)

eq(other) {
return other instanceof NodeSelection && this.from == other.from
}
map(doc, mapping) {
let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1)
let from = mapping.mapResult(this.anchor, 1), to = mapping.mapResult(this.head, -1)
let $from = doc.resolve(from.pos), node = $from.nodeAfter

@@ -215,6 +258,2 @@ if (!from.deleted && !to.deleted && node && to.pos == from.pos + node.nodeSize && NodeSelection.isSelectable(node))

toJSON() {
return {node: this.from, after: this.to}
}
// :: (Node, number, ?number) → TextSelection

@@ -232,5 +271,15 @@ // Create a node selection from non-resolved positions.

}
static fromJSON(doc, json) {
let $from = doc.resolve(json.anchor), node = $from.nodeAfter
if (node && json.head == json.anchor + node.nodeSize && NodeSelection.isSelectable(node)) return new NodeSelection($from)
else return Selection.near($from)
}
}
exports.NodeSelection = NodeSelection
NodeSelection.prototype.visible = false
Selection.jsonID("node", NodeSelection)
// FIXME we'll need some awareness of text direction when scanning for selections

@@ -242,3 +291,3 @@

function findSelectionIn(doc, node, pos, index, dir, text) {
if (node.isTextblock) return TextSelection.create(doc, pos)
if (node.inlineContent) return TextSelection.create(doc, pos)
for (let i = index - (dir > 0 ? 0 : 1); dir > 0 ? i < node.childCount : i >= 0; i += dir) {

@@ -245,0 +294,0 @@ let child = node.child(i)

@@ -16,3 +16,3 @@ const {Transform} = require("prosemirror-transform")

// metadata properties in a transaction, which are extra pieces of
// informations that client code or plugins can use to describe what a
// information that client code or plugins can use to describe what a
// transacion represents, so that they can update their [own

@@ -76,3 +76,3 @@ // state](##state.StateField) accordingly.

// :: (?[Mark]) → Transaction
// Replace the set of stored marks.
// Set the current stored marks.
setStoredMarks(marks) {

@@ -84,2 +84,12 @@ this.storedMarks = marks

// :: ([Mark]) → Transaction
// Make sure the current stored marks or, if that is null, the marks
// at the selection, match the given set of marks. Does nothing if
// this is already the case.
ensureMarks(marks) {
if (!Mark.sameSet(this.storedMarks || this.selection.$from.marks(), marks))
this.setStoredMarks(marks.length || this.storedMarks ? marks : null)
return this
}
// :: bool

@@ -137,4 +147,6 @@ // Whether the stored marks were explicitly set for this transaction.

deleteSelection() {
let {from, to} = this.selection
return this.deleteRange(from, to)
let {from, to, $from} = this.selection
this.deleteRange(from, to)
if ($from.parentOffset < $from.parent.content.size) this.ensureMarks($from.marks(true))
return this
}

@@ -194,4 +206,3 @@

addStoredMark(mark) {
this.storedMarks = mark.addToSet(this.storedMarks || currentMarks(this.selection))
return this
return this.ensureMarks(mark.addToSet(this.storedMarks || this.selection.$head.marks()))
}

@@ -202,4 +213,3 @@

removeStoredMark(mark) {
this.storedMarks = mark.removeFromSet(this.storedMarks || currentMarks(this.selection))
return this
return this.ensureMarks(mark.removeFromSet(this.storedMarks || this.selection.$head.marks()))
}

@@ -215,5 +225,1 @@ }

}
function currentMarks(selection) {
return selection.head == null ? Mark.none : selection.$head.marks()
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc