|
@@ -6,7 +6,7 @@ import {
|
|
|
} from '@phosphor/algorithm';
|
|
|
|
|
|
import {
|
|
|
- JSONExt, JSONValue
|
|
|
+ JSONExt
|
|
|
} from '@phosphor/coreutils';
|
|
|
|
|
|
import {
|
|
@@ -45,9 +45,12 @@ class CompleterModel implements CompleterWidget.IModel {
|
|
|
return this._original;
|
|
|
}
|
|
|
set original(newValue: CompleterWidget.ITextState) {
|
|
|
- if (Private.deepEqual(newValue, this._original)) {
|
|
|
+ let unchanged = this._original && newValue &&
|
|
|
+ JSONExt.deepEqual(newValue, this._original);
|
|
|
+ if (unchanged) {
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
this._reset();
|
|
|
this._original = newValue;
|
|
|
this._stateChanged.emit(void 0);
|
|
@@ -60,9 +63,12 @@ class CompleterModel implements CompleterWidget.IModel {
|
|
|
return this._current;
|
|
|
}
|
|
|
set current(newValue: CompleterWidget.ITextState) {
|
|
|
- if (Private.deepEqual(newValue, this._current)) {
|
|
|
+ let unchanged = this._current && newValue &&
|
|
|
+ JSONExt.deepEqual(newValue, this._current);
|
|
|
+ if (unchanged) {
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
// Original request must always be set before a text change. If it isn't
|
|
|
// the model fails silently.
|
|
|
if (!this.original) {
|
|
@@ -179,7 +185,7 @@ class CompleterModel implements CompleterWidget.IModel {
|
|
|
*/
|
|
|
setOptions(newValue: IterableOrArrayLike<string>) {
|
|
|
let values = toArray(newValue || []);
|
|
|
- if (Private.deepEqual(values, this._options)) {
|
|
|
+ if (JSONExt.deepEqual(values, this._options)) {
|
|
|
return;
|
|
|
}
|
|
|
if (values.length) {
|
|
@@ -252,23 +258,22 @@ class CompleterModel implements CompleterWidget.IModel {
|
|
|
let options = this._options || [];
|
|
|
let query = this._query;
|
|
|
if (!query) {
|
|
|
- return map(options, option => {
|
|
|
- return { raw: option, child: h.pre({}, option) };
|
|
|
- });
|
|
|
+ return map(options, option => ({ raw: option, text: option }));
|
|
|
}
|
|
|
let results: Private.IMatch[] = [];
|
|
|
for (let option of options) {
|
|
|
let match = StringExt.matchSumOfSquares(option, query);
|
|
|
if (match) {
|
|
|
+ let marked = StringExt.highlight(option, match.indices, Private.mark);
|
|
|
results.push({
|
|
|
raw: option,
|
|
|
score: match.score,
|
|
|
- child: StringExt.highlight(option, match.indices, h.mark)
|
|
|
+ text: marked.join('')
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
return map(results.sort(Private.scoreCmp), result =>
|
|
|
- ({ child: result.child, raw: result.raw })
|
|
|
+ ({ text: result.text, raw: result.raw })
|
|
|
);
|
|
|
}
|
|
|
|
|
@@ -317,9 +322,17 @@ namespace Private {
|
|
|
score: number;
|
|
|
|
|
|
/**
|
|
|
- * The virtual node of a completion match.
|
|
|
+ * The highlighted text of a completion match.
|
|
|
*/
|
|
|
- child: h.Child;
|
|
|
+ text: string;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Mark a highlighted chunk of text.
|
|
|
+ */
|
|
|
+ export
|
|
|
+ function mark(value: string): string {
|
|
|
+ return `<mark>${value}</mark>`;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -337,16 +350,4 @@ namespace Private {
|
|
|
}
|
|
|
return a.raw.localeCompare(b.raw);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * Compare two objects for JSON equality.
|
|
|
- */
|
|
|
- export
|
|
|
- function deepEqual(a: JSONValue, b: JSONValue): boolean {
|
|
|
- if (a === void 0 || b === void 0) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- return JSONExt.deepEqual(a, b);
|
|
|
- }
|
|
|
}
|