@codemirror/rangeset
Advanced tools
Comparing version 0.18.0 to 0.18.1
@@ -0,3 +1,13 @@ | ||
## 0.18.1 (2021-04-30) | ||
### Bug fixes | ||
When iterating spans and points, don't emit point ranges when they are entirely covered by a previous point. | ||
## 0.18.0 (2021-03-03) | ||
### Breaking changes | ||
Update dependencies to 0.18. | ||
## 0.17.1 (2021-01-06) | ||
@@ -4,0 +14,0 @@ |
import { MapMode, ChangeDesc } from '@codemirror/state'; | ||
/** | ||
Each range is associated with a value, which must inherit from | ||
this class. | ||
*/ | ||
declare abstract class RangeValue { | ||
/** | ||
Compare this value with another value. The default | ||
implementation compares by identity. | ||
*/ | ||
eq(other: RangeValue): boolean; | ||
/** | ||
The bias value at the start of the range. Determines how the | ||
range is positioned relative to other ranges starting at this | ||
position. Defaults to 0. | ||
*/ | ||
startSide: number; | ||
/** | ||
The bias value at the end of the range. Defaults to 0. | ||
*/ | ||
endSide: number; | ||
/** | ||
The mode with which the location of the range should be mapped | ||
when its `from` and `to` are the same, to decide whether a | ||
change deletes the range. Defaults to `MapMode.TrackDel`. | ||
*/ | ||
mapMode: MapMode; | ||
/** | ||
Whether this value marks a point range, which is treated as | ||
atomic and shadows the ranges contained in it. | ||
*/ | ||
point: boolean; | ||
/** | ||
Create a [range](https://codemirror.net/6/docs/ref/#rangeset.Range) with this value. | ||
*/ | ||
range(from: number, to?: number): Range<this>; | ||
} | ||
/** | ||
A range associates a value with a range of positions. | ||
*/ | ||
declare class Range<T extends RangeValue> { | ||
/** | ||
The range's start position. | ||
*/ | ||
readonly from: number; | ||
/** | ||
Its end position. | ||
*/ | ||
readonly to: number; | ||
/** | ||
The value associated with this range. | ||
*/ | ||
readonly value: T; | ||
} | ||
/** | ||
Collection of methods used when comparing range sets. | ||
*/ | ||
interface RangeComparator<T extends RangeValue> { | ||
/** | ||
Notifies the comparator that the given range has the given set | ||
of values associated with it. | ||
*/ | ||
compareRange(from: number, to: number, activeA: T[], activeB: T[]): void; | ||
/** | ||
Notification for a point range. | ||
*/ | ||
comparePoint(from: number, to: number, byA: T | null, byB: T | null): void; | ||
} | ||
/** | ||
Methods used when iterating over the spans created by a set of | ||
ranges. The entire iterated range will be covered with either | ||
`span` or `point` calls. | ||
*/ | ||
interface SpanIterator<T extends RangeValue> { | ||
/** | ||
Called for any ranges not covered by point decorations. `active` | ||
holds the values that the range is marked with (and may be | ||
empty). `openStart` indicates how many of those ranges are open | ||
(continued) at the start of the span. | ||
*/ | ||
span(from: number, to: number, active: readonly T[], openStart: number): void; | ||
/** | ||
Called when going over a point decoration. The active range | ||
decorations that cover the point and have a higher precedence | ||
are provided in `active`. The open count in `openStart` counts | ||
the number of those ranges that started before the point and. If | ||
the point started before the iterated range, `openStart` will be | ||
`active.length + 1` to signal this. | ||
*/ | ||
point(from: number, to: number, value: T, active: readonly T[], openStart: number): void; | ||
} | ||
/** | ||
A range cursor is an object that moves to the next range every | ||
time you call `next` on it. Note that, unlike ES6 iterators, these | ||
start out pointing at the first element, so you should call `next` | ||
only after reading the first range (if any). | ||
*/ | ||
interface RangeCursor<T> { | ||
/** | ||
Move the iterator forward. | ||
*/ | ||
next: () => void; | ||
/** | ||
The next range's value. Holds `null` when the cursor has reached | ||
its end. | ||
*/ | ||
value: T | null; | ||
/** | ||
The next range's start position. | ||
*/ | ||
from: number; | ||
/** | ||
The next end position. | ||
*/ | ||
to: number; | ||
} | ||
declare type RangeSetUpdate<T extends RangeValue> = { | ||
/** | ||
An array of ranges to add. If given, this should be sorted by | ||
`from` position and `startSide` unless | ||
[`sort`](https://codemirror.net/6/docs/ref/#rangeset.RangeSet.update^updateSpec.sort) is given as | ||
`true`. | ||
*/ | ||
add?: readonly Range<T>[]; | ||
/** | ||
Indicates whether the library should sort the ranges in `add`. | ||
Defaults to `false`. | ||
*/ | ||
sort?: boolean; | ||
/** | ||
Filter the ranges already in the set. Only those for which this | ||
function returns `true` are kept. | ||
*/ | ||
filter?: (from: number, to: number, value: T) => boolean; | ||
/** | ||
Can be used to limit the range on which the filter is | ||
applied. Filtering only a small range, as opposed to the entire | ||
set, can make updates cheaper. | ||
*/ | ||
filterFrom?: number; | ||
/** | ||
The end position to apply the filter to. | ||
*/ | ||
filterTo?: number; | ||
}; | ||
/** | ||
A range set stores a collection of [ranges](https://codemirror.net/6/docs/ref/#rangeset.Range) in a | ||
way that makes them efficient to [map](https://codemirror.net/6/docs/ref/#rangeset.RangeSet.map) and | ||
[update](https://codemirror.net/6/docs/ref/#rangeset.RangeSet.update). This is an immutable data | ||
structure. | ||
*/ | ||
declare class RangeSet<T extends RangeValue> { | ||
/** | ||
The number of ranges in the set. | ||
*/ | ||
get size(): number; | ||
/** | ||
Update the range set, optionally adding new ranges or filtering | ||
out existing ones. | ||
(The extra type parameter is just there as a kludge to work | ||
around TypeScript variance issues that prevented `RangeSet<X>` | ||
from being a subtype of `RangeSet<Y>` when `X` is a subtype of | ||
`Y`.) | ||
*/ | ||
update<U extends T>(updateSpec: RangeSetUpdate<U>): RangeSet<T>; | ||
/** | ||
Map this range set through a set of changes, return the new set. | ||
*/ | ||
map(changes: ChangeDesc): RangeSet<T>; | ||
/** | ||
Iterate over the ranges that touch the region `from` to `to`, | ||
calling `f` for each. There is no guarantee that the ranges will | ||
be reported in any specific order. When the callback returns | ||
`false`, iteration stops. | ||
*/ | ||
between(from: number, to: number, f: (from: number, to: number, value: T) => void | false): void; | ||
/** | ||
Iterate over the ranges in this set, in order, including all | ||
ranges that end at or after `from`. | ||
*/ | ||
iter(from?: number): RangeCursor<T>; | ||
/** | ||
Iterate over the ranges in a collection of sets, in order, | ||
starting from `from`. | ||
*/ | ||
static iter<T extends RangeValue>(sets: readonly RangeSet<T>[], from?: number): RangeCursor<T>; | ||
static compare<T extends RangeValue>(oldSets: readonly RangeSet<T>[], newSets: readonly RangeSet<T>[], textDiff: ChangeDesc, comparator: RangeComparator<T>, minPointSize?: number): void; | ||
static spans<T extends RangeValue>(sets: readonly RangeSet<T>[], from: number, to: number, iterator: SpanIterator<T>, minPointSize?: number): number; | ||
/** | ||
Iterate over two groups of sets, calling methods on `comparator` | ||
to notify it of possible differences. | ||
*/ | ||
static compare<T extends RangeValue>(oldSets: readonly RangeSet<T>[], newSets: readonly RangeSet<T>[], | ||
/** | ||
This indicates how the underlying data changed between these | ||
ranges, and is needed to synchronize the iteration. `from` and | ||
`to` are coordinates in the _new_ space, after these changes. | ||
*/ | ||
textDiff: ChangeDesc, comparator: RangeComparator<T>, | ||
/** | ||
Can be used to ignore all non-point ranges, and points below | ||
the given size. When -1, all ranges are compared. | ||
*/ | ||
minPointSize?: number): void; | ||
/** | ||
Iterate over a group of range sets at the same time, notifying | ||
the iterator about the ranges covering every given piece of | ||
content. Returns the open count (see | ||
[`SpanIterator.span`](https://codemirror.net/6/docs/ref/#rangeset.SpanIterator.span)) at the end | ||
of the iteration. | ||
*/ | ||
static spans<T extends RangeValue>(sets: readonly RangeSet<T>[], from: number, to: number, iterator: SpanIterator<T>, | ||
/** | ||
When given and greater than -1, only points of at least this | ||
size are taken into account. | ||
*/ | ||
minPointSize?: number): number; | ||
/** | ||
Create a range set for the given range or array of ranges. By | ||
default, this expects the ranges to be _sorted_ (by start | ||
position and, if two start at the same position, | ||
`value.startSide`). You can pass `true` as second argument to | ||
cause the method to sort them. | ||
*/ | ||
static of<T extends RangeValue>(ranges: readonly Range<T>[] | Range<T>, sort?: boolean): RangeSet<T>; | ||
/** | ||
The empty set of ranges. | ||
*/ | ||
static empty: RangeSet<any>; | ||
} | ||
/** | ||
A range set builder is a data structure that helps build up a | ||
[range set](https://codemirror.net/6/docs/ref/#rangeset.RangeSet) directly, without first allocating | ||
an array of [`Range`](https://codemirror.net/6/docs/ref/#rangeset.Range) objects. | ||
*/ | ||
declare class RangeSetBuilder<T extends RangeValue> { | ||
@@ -63,4 +250,15 @@ private chunks; | ||
private finishChunk; | ||
/** | ||
Create an empty builder. | ||
*/ | ||
constructor(); | ||
/** | ||
Add a range. Ranges should be added in sorted (by `from` and | ||
`value.startSide`) order. | ||
*/ | ||
add(from: number, to: number, value: T): void; | ||
/** | ||
Finish the range set. Returns the new set. The builder can't be | ||
used anymore after this has been called. | ||
*/ | ||
finish(): RangeSet<T>; | ||
@@ -67,0 +265,0 @@ } |
import { MapMode } from '@codemirror/state'; | ||
/// Each range is associated with a value, which must inherit from | ||
/// this class. | ||
/** | ||
Each range is associated with a value, which must inherit from | ||
this class. | ||
*/ | ||
class RangeValue { | ||
/// Compare this value with another value. The default | ||
/// implementation compares by identity. | ||
/** | ||
Compare this value with another value. The default | ||
implementation compares by identity. | ||
*/ | ||
eq(other) { return this == other; } | ||
/// Create a [range](#rangeset.Range) with this value. | ||
/** | ||
Create a [range](https://codemirror.net/6/docs/ref/#rangeset.Range) with this value. | ||
*/ | ||
range(from, to = from) { return new Range(from, to, this); } | ||
@@ -15,11 +21,21 @@ } | ||
RangeValue.prototype.mapMode = MapMode.TrackDel; | ||
/// A range associates a value with a range of positions. | ||
/** | ||
A range associates a value with a range of positions. | ||
*/ | ||
class Range { | ||
/// @internal | ||
/** | ||
@internal | ||
*/ | ||
constructor( | ||
/// The range's start position. | ||
/** | ||
The range's start position. | ||
*/ | ||
from, | ||
/// Its end position. | ||
/** | ||
Its end position. | ||
*/ | ||
to, | ||
/// The value associated with this range. | ||
/** | ||
The value associated with this range. | ||
*/ | ||
value) { | ||
@@ -100,16 +116,28 @@ this.from = from; | ||
} | ||
/// A range set stores a collection of [ranges](#rangeset.Range) in a | ||
/// way that makes them efficient to [map](#rangeset.RangeSet.map) and | ||
/// [update](#rangeset.RangeSet.update). This is an immutable data | ||
/// structure. | ||
/** | ||
A range set stores a collection of [ranges](https://codemirror.net/6/docs/ref/#rangeset.Range) in a | ||
way that makes them efficient to [map](https://codemirror.net/6/docs/ref/#rangeset.RangeSet.map) and | ||
[update](https://codemirror.net/6/docs/ref/#rangeset.RangeSet.update). This is an immutable data | ||
structure. | ||
*/ | ||
class RangeSet { | ||
/// @internal | ||
/** | ||
@internal | ||
*/ | ||
constructor( | ||
/// @internal | ||
/** | ||
@internal | ||
*/ | ||
chunkPos, | ||
/// @internal | ||
/** | ||
@internal | ||
*/ | ||
chunk, | ||
/// @internal | ||
/** | ||
@internal | ||
*/ | ||
nextLayer = RangeSet.empty, | ||
/// @internal | ||
/** | ||
@internal | ||
*/ | ||
maxPoint) { | ||
@@ -121,3 +149,5 @@ this.chunkPos = chunkPos; | ||
} | ||
/// @internal | ||
/** | ||
@internal | ||
*/ | ||
get length() { | ||
@@ -127,3 +157,5 @@ let last = this.chunk.length - 1; | ||
} | ||
/// The number of ranges in the set. | ||
/** | ||
The number of ranges in the set. | ||
*/ | ||
get size() { | ||
@@ -137,13 +169,17 @@ if (this == RangeSet.empty) | ||
} | ||
/// @internal | ||
/** | ||
@internal | ||
*/ | ||
chunkEnd(index) { | ||
return this.chunkPos[index] + this.chunk[index].length; | ||
} | ||
/// Update the range set, optionally adding new ranges or filtering | ||
/// out existing ones. | ||
/// | ||
/// (The extra type parameter is just there as a kludge to work | ||
/// around TypeScript variance issues that prevented `RangeSet<X>` | ||
/// from being a subtype of `RangeSet<Y>` when `X` is a subtype of | ||
/// `Y`.) | ||
/** | ||
Update the range set, optionally adding new ranges or filtering | ||
out existing ones. | ||
(The extra type parameter is just there as a kludge to work | ||
around TypeScript variance issues that prevented `RangeSet<X>` | ||
from being a subtype of `RangeSet<Y>` when `X` is a subtype of | ||
`Y`.) | ||
*/ | ||
update(updateSpec) { | ||
@@ -183,3 +219,5 @@ let { add = [], sort = false, filterFrom = 0, filterTo = this.length } = updateSpec; | ||
} | ||
/// Map this range set through a set of changes, return the new set. | ||
/** | ||
Map this range set through a set of changes, return the new set. | ||
*/ | ||
map(changes) { | ||
@@ -209,6 +247,8 @@ if (changes.length == 0 || this == RangeSet.empty) | ||
} | ||
/// Iterate over the ranges that touch the region `from` to `to`, | ||
/// calling `f` for each. There is no guarantee that the ranges will | ||
/// be reported in any specific order. When the callback returns | ||
/// `false`, iteration stops. | ||
/** | ||
Iterate over the ranges that touch the region `from` to `to`, | ||
calling `f` for each. There is no guarantee that the ranges will | ||
be reported in any specific order. When the callback returns | ||
`false`, iteration stops. | ||
*/ | ||
between(from, to, f) { | ||
@@ -225,21 +265,31 @@ if (this == RangeSet.empty) | ||
} | ||
/// Iterate over the ranges in this set, in order, including all | ||
/// ranges that end at or after `from`. | ||
/** | ||
Iterate over the ranges in this set, in order, including all | ||
ranges that end at or after `from`. | ||
*/ | ||
iter(from = 0) { | ||
return HeapCursor.from([this]).goto(from); | ||
} | ||
/// Iterate over the ranges in a collection of sets, in order, | ||
/// starting from `from`. | ||
/** | ||
Iterate over the ranges in a collection of sets, in order, | ||
starting from `from`. | ||
*/ | ||
static iter(sets, from = 0) { | ||
return HeapCursor.from(sets).goto(from); | ||
} | ||
/// Iterate over two groups of sets, calling methods on `comparator` | ||
/// to notify it of possible differences. | ||
/** | ||
Iterate over two groups of sets, calling methods on `comparator` | ||
to notify it of possible differences. | ||
*/ | ||
static compare(oldSets, newSets, | ||
/// This indicates how the underlying data changed between these | ||
/// ranges, and is needed to synchronize the iteration. `from` and | ||
/// `to` are coordinates in the _new_ space, after these changes. | ||
/** | ||
This indicates how the underlying data changed between these | ||
ranges, and is needed to synchronize the iteration. `from` and | ||
`to` are coordinates in the _new_ space, after these changes. | ||
*/ | ||
textDiff, comparator, | ||
/// Can be used to ignore all non-point ranges, and points below | ||
/// the given size. When -1, all ranges are compared. | ||
/** | ||
Can be used to ignore all non-point ranges, and points below | ||
the given size. When -1, all ranges are compared. | ||
*/ | ||
minPointSize = -1) { | ||
@@ -257,10 +307,14 @@ let a = oldSets.filter(set => set.maxPoint >= 500 /* BigPointSize */ || | ||
} | ||
/// Iterate over a group of range sets at the same time, notifying | ||
/// the iterator about the ranges covering every given piece of | ||
/// content. Returns the open count (see | ||
/// [`SpanIterator.span`](#rangeset.SpanIterator.span)) at the end | ||
/// of the iteration. | ||
/** | ||
Iterate over a group of range sets at the same time, notifying | ||
the iterator about the ranges covering every given piece of | ||
content. Returns the open count (see | ||
[`SpanIterator.span`](https://codemirror.net/6/docs/ref/#rangeset.SpanIterator.span)) at the end | ||
of the iteration. | ||
*/ | ||
static spans(sets, from, to, iterator, | ||
/// When given and greater than -1, only points of at least this | ||
/// size are taken into account. | ||
/** | ||
When given and greater than -1, only points of at least this | ||
size are taken into account. | ||
*/ | ||
minPointSize = -1) { | ||
@@ -286,7 +340,9 @@ let cursor = new SpanCursor(sets, null, minPointSize).goto(from), pos = from; | ||
} | ||
/// Create a range set for the given range or array of ranges. By | ||
/// default, this expects the ranges to be _sorted_ (by start | ||
/// position and, if two start at the same position, | ||
/// `value.startSide`). You can pass `true` as second argument to | ||
/// cause the method to sort them. | ||
/** | ||
Create a range set for the given range or array of ranges. By | ||
default, this expects the ranges to be _sorted_ (by start | ||
position and, if two start at the same position, | ||
`value.startSide`). You can pass `true` as second argument to | ||
cause the method to sort them. | ||
*/ | ||
static of(ranges, sort = false) { | ||
@@ -299,10 +355,16 @@ let build = new RangeSetBuilder(); | ||
} | ||
/// The empty set of ranges. | ||
RangeSet.empty = new RangeSet([], [], null, -1); | ||
/** | ||
The empty set of ranges. | ||
*/ | ||
RangeSet.empty = /*@__PURE__*/new RangeSet([], [], null, -1); | ||
RangeSet.empty.nextLayer = RangeSet.empty; | ||
/// A range set builder is a data structure that helps build up a | ||
/// [range set](#rangeset.RangeSet) directly, without first allocating | ||
/// an array of [`Range`](#rangeset.Range) objects. | ||
/** | ||
A range set builder is a data structure that helps build up a | ||
[range set](https://codemirror.net/6/docs/ref/#rangeset.RangeSet) directly, without first allocating | ||
an array of [`Range`](https://codemirror.net/6/docs/ref/#rangeset.Range) objects. | ||
*/ | ||
class RangeSetBuilder { | ||
/// Create an empty builder. | ||
/** | ||
Create an empty builder. | ||
*/ | ||
constructor() { | ||
@@ -334,4 +396,6 @@ this.chunks = []; | ||
} | ||
/// Add a range. Ranges should be added in sorted (by `from` and | ||
/// `value.startSide`) order. | ||
/** | ||
Add a range. Ranges should be added in sorted (by `from` and | ||
`value.startSide`) order. | ||
*/ | ||
add(from, to, value) { | ||
@@ -341,3 +405,5 @@ if (!this.addInner(from, to, value)) | ||
} | ||
/// @internal | ||
/** | ||
@internal | ||
*/ | ||
addInner(from, to, value) { | ||
@@ -363,3 +429,5 @@ let diff = from - this.lastTo || value.startSide - this.last.endSide; | ||
} | ||
/// @internal | ||
/** | ||
@internal | ||
*/ | ||
addChunk(from, chunk) { | ||
@@ -379,6 +447,10 @@ if ((from - this.lastTo || chunk.value[0].startSide - this.last.endSide) < 0) | ||
} | ||
/// Finish the range set. Returns the new set. The builder can't be | ||
/// used anymore after this has been called. | ||
/** | ||
Finish the range set. Returns the new set. The builder can't be | ||
used anymore after this has been called. | ||
*/ | ||
finish() { return this.finishInner(RangeSet.empty); } | ||
/// @internal | ||
/** | ||
@internal | ||
*/ | ||
finishInner(next) { | ||
@@ -593,3 +665,3 @@ if (this.from.length) | ||
next() { | ||
let from = this.to; | ||
let from = this.to, wasPoint = this.point; | ||
this.point = null; | ||
@@ -624,2 +696,6 @@ let trackOpen = this.openStart < 0 ? [] : null, trackExtra = 0; | ||
} | ||
else if (wasPoint && this.cursor.to == this.to && this.cursor.from < this.cursor.to && nextVal.endSide == this.endSide) { | ||
// Ignore any non-empty points that end precisely at the end of the prev point | ||
this.cursor.next(); | ||
} | ||
else { // New point | ||
@@ -626,0 +702,0 @@ this.point = nextVal; |
{ | ||
"name": "@codemirror/rangeset", | ||
"version": "0.18.0", | ||
"version": "0.18.1", | ||
"description": "Range set data structure for the CodeMirror code editor", | ||
"scripts": { | ||
"test": "mocha test/test-*.js", | ||
"prepare": "tsc -p tsconfig.local.json && rollup -c" | ||
"test": "cm-runtests", | ||
"prepare": "cm-buildhelper src/rangeset.ts" | ||
}, | ||
@@ -32,8 +32,3 @@ "keywords": [ | ||
"devDependencies": { | ||
"rollup": "^2.35.1", | ||
"rollup-plugin-dts": "^2.0.1", | ||
"typescript": "^4.1.3", | ||
"@types/mocha": "^5.2.0", | ||
"ist": "^1.1.6", | ||
"mocha": "^7.1.1" | ||
"@codemirror/buildhelper": "^0.1.5" | ||
}, | ||
@@ -40,0 +35,0 @@ "repository": { |
Sorry, the diff of this file is not supported yet
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
1
1818
68773
8