mirror of
https://github.com/zulip/zulip.git
synced 2025-11-06 23:13:25 +00:00
typescript: Migrate dict.js to typescript.
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
set_global('i18n', global.stub_i18n);
|
set_global('i18n', global.stub_i18n);
|
||||||
zrequire('dict');
|
|
||||||
zrequire('compose_state');
|
zrequire('compose_state');
|
||||||
zrequire('ui_util');
|
zrequire('ui_util');
|
||||||
zrequire('pm_conversations');
|
zrequire('pm_conversations');
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
zrequire('dict');
|
|
||||||
zrequire('user_pill');
|
zrequire('user_pill');
|
||||||
zrequire('settings_user_groups');
|
zrequire('settings_user_groups');
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
set_global('blueslip', global.make_zblueslip());
|
set_global('blueslip', global.make_zblueslip());
|
||||||
set_global('page_params', {});
|
set_global('page_params', {});
|
||||||
|
|
||||||
zrequire('dict');
|
|
||||||
zrequire('user_groups');
|
zrequire('user_groups');
|
||||||
|
|
||||||
run_test('user_groups', () => {
|
run_test('user_groups', () => {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ global.window = _.extend({}, windowObj, {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
global.Dict = require('js/dict');
|
global.Dict = require('ts/dict.ts').Dict;
|
||||||
|
|
||||||
// Create a helper function to avoid sneaky delays in tests.
|
// Create a helper function to avoid sneaky delays in tests.
|
||||||
function immediate(f) {
|
function immediate(f) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "8.0.34",
|
"@types/node": "8.0.34",
|
||||||
"@types/webpack": "4.4.0",
|
"@types/webpack": "4.4.0",
|
||||||
|
"@types/underscore": "1.8.9",
|
||||||
"blueimp-md5": "2.10.0",
|
"blueimp-md5": "2.10.0",
|
||||||
"clipboard": "2.0.1",
|
"clipboard": "2.0.1",
|
||||||
"css-hot-loader": "1.3.9",
|
"css-hot-loader": "1.3.9",
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var activity = (function () {
|
var activity = (function () {
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import "js/search_util.js";
|
|||||||
import "js/keydown_util.js";
|
import "js/keydown_util.js";
|
||||||
import "js/lightbox_canvas.js";
|
import "js/lightbox_canvas.js";
|
||||||
import "js/rtl.js";
|
import "js/rtl.js";
|
||||||
import "js/dict.js";
|
import "ts/dict.ts";
|
||||||
import "js/scroll_util.js";
|
import "js/scroll_util.js";
|
||||||
import "js/components.js";
|
import "js/components.js";
|
||||||
import "js/feedback_widget.js";
|
import "js/feedback_widget.js";
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var color_data = (function () {
|
var color_data = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var condense = (function () {
|
var condense = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,144 +0,0 @@
|
|||||||
/* Constructs a new Dict object.
|
|
||||||
*
|
|
||||||
* This module primarily exists to support the fold_case option,
|
|
||||||
* because so many string keys in Zulip are case-insensitive (emails,
|
|
||||||
* stream names, topics, etc.).
|
|
||||||
*
|
|
||||||
* Dict(opt) -> the new Dict will be empty
|
|
||||||
*
|
|
||||||
* Available options:
|
|
||||||
* fold_case - Make has() and get() case-insensitive. keys() and
|
|
||||||
* other methods that implicitly return keys return the
|
|
||||||
* casing used for the most recent set()
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function Dict(opts) {
|
|
||||||
this._items = {};
|
|
||||||
this._opts = _.extend({}, {fold_case: false}, opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Constructs a new Dict object from another object.
|
|
||||||
*
|
|
||||||
* Dict.from(jsobj, opts) -> create a Dict with keys corresponding to the
|
|
||||||
* properties of jsobj and values corresponding to
|
|
||||||
* the value of the appropriate property. `opts` is
|
|
||||||
* passed to the Dict constructor.
|
|
||||||
*/
|
|
||||||
Dict.from = function Dict_from(obj, opts) {
|
|
||||||
if (typeof obj !== "object" || obj === null) {
|
|
||||||
throw new TypeError("Cannot convert argument to Dict");
|
|
||||||
}
|
|
||||||
|
|
||||||
var ret = new Dict(opts);
|
|
||||||
_.each(obj, function (val, key) {
|
|
||||||
ret.set(key, val);
|
|
||||||
});
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Like above, but constructs a Dict object from an array, setting the value of
|
|
||||||
* each element to `true`. Intended for use as a set. As above, `opts` is
|
|
||||||
* passed to the Dict constructor.
|
|
||||||
*/
|
|
||||||
Dict.from_array = function Dict_from_array(xs, opts) {
|
|
||||||
if (!(xs instanceof Array)) {
|
|
||||||
throw new TypeError("Argument is not an array");
|
|
||||||
}
|
|
||||||
|
|
||||||
var ret = new Dict(opts);
|
|
||||||
_.each(xs, function (x) {
|
|
||||||
ret.set(x, true);
|
|
||||||
});
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
Dict.prototype = {
|
|
||||||
_munge: function Dict__munge(k) {
|
|
||||||
if (k === undefined) {
|
|
||||||
blueslip.error("Tried to call a Dict method with an undefined key.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this._opts.fold_case) {
|
|
||||||
k = k.toLowerCase();
|
|
||||||
}
|
|
||||||
return ':' + k;
|
|
||||||
},
|
|
||||||
|
|
||||||
clone: function Dict_clone() {
|
|
||||||
var ret = new Dict(this._opts);
|
|
||||||
ret._items = _.clone(this._items);
|
|
||||||
return ret;
|
|
||||||
},
|
|
||||||
|
|
||||||
get: function Dict_get(key) {
|
|
||||||
var mapping = this._items[this._munge(key)];
|
|
||||||
if (mapping === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return mapping.v;
|
|
||||||
},
|
|
||||||
|
|
||||||
set: function Dict_set(key, value) {
|
|
||||||
this._items[this._munge(key)] = {k: key, v: value};
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
|
|
||||||
// If `key` exists in the Dict, return its value. Otherwise
|
|
||||||
// insert `key` with a value of `value` and return `value`.
|
|
||||||
setdefault: function Dict_setdefault(key, value) {
|
|
||||||
var mapping = this._items[this._munge(key)];
|
|
||||||
if (mapping === undefined) {
|
|
||||||
return this.set(key, value);
|
|
||||||
}
|
|
||||||
return mapping.v;
|
|
||||||
},
|
|
||||||
|
|
||||||
has: function Dict_has(key) {
|
|
||||||
return _.has(this._items, this._munge(key));
|
|
||||||
},
|
|
||||||
|
|
||||||
del: function Dict_del(key) {
|
|
||||||
return delete this._items[this._munge(key)];
|
|
||||||
},
|
|
||||||
|
|
||||||
keys: function Dict_keys() {
|
|
||||||
return _.pluck(_.values(this._items), 'k');
|
|
||||||
},
|
|
||||||
|
|
||||||
values: function Dict_values() {
|
|
||||||
return _.pluck(_.values(this._items), 'v');
|
|
||||||
},
|
|
||||||
|
|
||||||
items: function Dict_items() {
|
|
||||||
return _.map(_.values(this._items), function (mapping) {
|
|
||||||
return [mapping.k, mapping.v];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
num_items: function Dict_num_items() {
|
|
||||||
return _.keys(this._items).length;
|
|
||||||
},
|
|
||||||
|
|
||||||
is_empty: function Dict_is_empty() {
|
|
||||||
return _.isEmpty(this._items);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Iterates through the Dict calling f(value, key) for each (key, value) pair in the Dict
|
|
||||||
each: function Dict_each(f) {
|
|
||||||
return _.each(this._items, function (mapping) {
|
|
||||||
f(mapping.v, mapping.k);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
clear: function Dict_clear() {
|
|
||||||
this._items = {};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
}());
|
|
||||||
|
|
||||||
if (typeof module !== 'undefined') {
|
|
||||||
module.exports = Dict;
|
|
||||||
}
|
|
||||||
window.Dict = Dict;
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var muting = (function () {
|
var muting = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var narrow_state = (function () {
|
var narrow_state = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var people = (function () {
|
var people = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var pm_conversations = (function () {
|
var pm_conversations = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var reactions = (function () {
|
var reactions = (function () {
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var recent_senders = (function () {
|
var recent_senders = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var settings_sections = (function () {
|
var settings_sections = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var settings_streams = (function () {
|
var settings_streams = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var starred_messages = (function () {
|
var starred_messages = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var stream_data = (function () {
|
var stream_data = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var stream_list = (function () {
|
var stream_list = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var topic_data = (function () {
|
var topic_data = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var topic_list = (function () {
|
var topic_list = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var typeahead_helper = (function () {
|
var typeahead_helper = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var typing_data = (function () {
|
var typing_data = (function () {
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
// See https://zulip.readthedocs.io/en/latest/subsystems/pointer.html for notes on
|
// See https://zulip.readthedocs.io/en/latest/subsystems/pointer.html for notes on
|
||||||
// how this system is designed.
|
// how this system is designed.
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var user_groups = (function () {
|
var user_groups = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
var Dict = require('../ts/dict').Dict;
|
||||||
|
|
||||||
var user_status = (function () {
|
var user_status = (function () {
|
||||||
|
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|||||||
149
static/ts/dict.ts
Normal file
149
static/ts/dict.ts
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
import * as _ from 'underscore';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation detail of the Dict class. `key` is `k` converted to a string,
|
||||||
|
* in lowercase if the `fold_case` option is enabled.
|
||||||
|
*/
|
||||||
|
type KeyValue<K, V> = { k: K, v: V }
|
||||||
|
type Items<K, V> = {
|
||||||
|
[key: string]: KeyValue<K, V>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class primarily exists to support the fold_case option, because so many
|
||||||
|
* string keys in Zulip are case-insensitive (emails, stream names, topics,
|
||||||
|
* etc.). Dict also accepts any key that can be converted to a string.
|
||||||
|
*/
|
||||||
|
export class Dict<K, V> {
|
||||||
|
private _items: Items<K, V> = {};
|
||||||
|
private _fold_case: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param opts - setting `fold_case` to true will make `has()` and `get()`
|
||||||
|
* case-insensitive. `keys()` and other methods that
|
||||||
|
* implicitly return keys return the original casing/type
|
||||||
|
* of the key passed into `set()`.
|
||||||
|
*/
|
||||||
|
constructor(opts?: {fold_case: boolean}) {
|
||||||
|
this._fold_case = opts ? opts.fold_case : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Dict object from an existing object's keys and values.
|
||||||
|
* @param obj - A javascript object
|
||||||
|
* @param opts - Options to be passed to the Dict constructor
|
||||||
|
*/
|
||||||
|
static from<V>(obj: { [key: string]: V }, opts?: {fold_case: boolean}): Dict<string, V> {
|
||||||
|
if (typeof obj !== "object" || obj === null) {
|
||||||
|
throw new TypeError("Cannot convert argument to Dict");
|
||||||
|
}
|
||||||
|
|
||||||
|
let dict = new Dict<string, V>(opts);
|
||||||
|
for (const key in obj) {
|
||||||
|
dict.set(key, obj[key]);
|
||||||
|
}
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a Dict object from an array with each element set to `true`.
|
||||||
|
* Intended for use as a set data structure.
|
||||||
|
* @param arr - An array of keys
|
||||||
|
* @param opts - Options to be passed to the Dict constructor
|
||||||
|
*/
|
||||||
|
static from_array<K, V>(arr: K[], opts?: {fold_case: boolean}): Dict<K, V | true> {
|
||||||
|
if (!(arr instanceof Array)) {
|
||||||
|
throw new TypeError("Argument is not an array");
|
||||||
|
}
|
||||||
|
|
||||||
|
let dict = new Dict<K, V | true>(opts);
|
||||||
|
for (const key of arr) {
|
||||||
|
dict.set(key, true);
|
||||||
|
}
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle case-folding of keys and the empty string.
|
||||||
|
private _munge(key: K): string | undefined {
|
||||||
|
if (key === undefined) {
|
||||||
|
blueslip.error("Tried to call a Dict method with an undefined key.");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
let str_key = ':' + key.toString();
|
||||||
|
return this._fold_case ? str_key.toLowerCase() : str_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
clone(): Dict<K, V> {
|
||||||
|
let dict = new Dict<K, V>({fold_case: this._fold_case});
|
||||||
|
dict._items = { ...this._items };
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key: K): V | undefined {
|
||||||
|
const mapping = this._items[this._munge(key)];
|
||||||
|
if (mapping === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return mapping.v;
|
||||||
|
}
|
||||||
|
|
||||||
|
set(key: K, value: V): V {
|
||||||
|
this._items[this._munge(key)] = {k: key, v: value};
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If `key` exists in the Dict, return its value. Otherwise insert `key`
|
||||||
|
* with a value of `value` and return the value.
|
||||||
|
*/
|
||||||
|
setdefault(key: K, value: V): V {
|
||||||
|
const mapping = this._items[this._munge(key)];
|
||||||
|
if (mapping === undefined) {
|
||||||
|
return this.set(key, value);
|
||||||
|
}
|
||||||
|
return mapping.v;
|
||||||
|
}
|
||||||
|
|
||||||
|
has(key: K): boolean {
|
||||||
|
return _.has(this._items, this._munge(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
del(key: K): boolean {
|
||||||
|
// `delete` could throw a TypeError in strict mode.
|
||||||
|
try {
|
||||||
|
delete this._items[this._munge(key)];
|
||||||
|
} catch (_e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
keys(): K[] {
|
||||||
|
return _.pluck(_.values(this._items), 'k');
|
||||||
|
}
|
||||||
|
|
||||||
|
values(): V[] {
|
||||||
|
return _.pluck(_.values(this._items), 'v');
|
||||||
|
}
|
||||||
|
|
||||||
|
items(): [K, V][] {
|
||||||
|
return _.map(_.values(this._items),
|
||||||
|
(mapping: KeyValue<K, V>): [K, V] => [mapping.k, mapping.v]);
|
||||||
|
}
|
||||||
|
|
||||||
|
num_items(): number {
|
||||||
|
return _.keys(this._items).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_empty(): boolean {
|
||||||
|
return _.isEmpty(this._items);
|
||||||
|
}
|
||||||
|
|
||||||
|
each(f: (v: V, k?: K) => void) {
|
||||||
|
_.each(this._items, (mapping: KeyValue<K, V>) => f(mapping.v, mapping.k));
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this._items = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user