yanweiyuan3
2023-08-09 588bc7829387dfc761cc25f06f77d4c81818bd10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/**
 * Asynchronous every that allows asynchronous function as its predicate.
 *
 * @param array An array of items
 * @param predicate Asynchronous function to determine if each of the items in the provided array satisfies the criteria
 * @example
 * let testArr: number[] = [10, 20, 3, 40];
 * let isBigEnough = await asyncEvery(testArr, async (num: number) => {
 * let threshold = await this.getThresholdNo();
 * return num >= threshold;
 * });
 * // if threshold is 10, isBigEnough is false because 3 is not >= 10.
 * // if threshold is 3, isBigEnough is true.
 */
export const asyncEvery = async <T>(array: T[], predicate: (value: T) => Promise<boolean>): Promise<boolean> => {
  for (const item of array) {
    if (!(await predicate(item))) {
      return false;
    }
  }
  return true;
};
 
/**
 * Similar to `Array.prototype.filter`, but this supports async actions.
 *
 * @param array An array of items to be filtered
 * @param callback Asynchronous function to perform filtering
 * @returns `T[]` a newly filtered array.
 */
export const asyncFilter = async <T>(array: T[], callback: (value: T, index: number, array: T[]) => Promise<boolean>): Promise<T[]> => {
  const filterMap = await asyncMap(array, callback);
  return array.filter((_: T, index: number) => filterMap[index]);
};
 
/**
 * Similar to `Array.prototype.map`, but this supports async actions.
 *
 * @template T Type of the item for the array to be mapped from.
 * @template U Type of the item for the mapped array.
 * @param array An array of items to be mapped from.
 * @param callback Asynchronous function to perform an array mapping
 * @returns `U[]` A new mapped array.
 * @example
 * const array = [1, 5, 7, 10];
 * // example to simulate getting some items from online list based on the collection of ids above.
 * const mappedArr = await asyncMap(array, async (id: number) => {
 * const listItems = await this.getItemsFromList(id);
 * return listItems;
 * })
 */
export const asyncMap = async <T, U>(array: T[], callback: (value: T, index: number, array: T[]) => Promise<U>): Promise<U[]> => Promise.all(array.map(callback));
 
/**
 * Find all the HTML elements by HTML tag name from a HTML string
 *
 * @param htmlString Target HTML string to retrieve HTML elements
 * @param tagName Target tag name to find
 * @example this.findHtmlElementByTag(tooltip, 'tr');
 *
 * @return All the html elements found
 */
export const findHtmlElementByTag = (htmlString: string, tagName: string): string[] | null => {
  const htmlElregex = new RegExp(`<${tagName}.*?>(.*?)<\/${tagName}>`, 'g');
  const htmlElements = htmlString.match(htmlElregex);
 
  return htmlElements;
};
 
/**
 * Obtains key entries from a given enumerator.
 *
 * @param e `EnumLike`: EnumLike object / enumerator.
 * @returns `string[]`: which consists of key entries.
 * @example
 * enum Example {
 * A,
 * B,
 * C = 'ccc',
 * D = 1,
 * }
 *
 * getEnumKeyEntries(Example); // returns ['A', 'B', 'C', 'D']
 */
export const getEnumKeyEntries: (e: EnumLike) => string[] = (e: EnumLike): string[] => Object.keys(e).filter((key: string) => isNaN(Number(key)));
 
/**
 * Obtains value entries from a given enumerator.
 *
 * @param e `EnumLike`: EnumLike object / enumerator.
 * @returns `(string | number)[]`: array which contains string and/or number, which are thee value entries.
 * @example
 * enum Example {
 * A,
 * B,
 * C = 'ccc',
 * D = 1,
 * }
 *
 * getEnumValueEntries(Example); // returns ['AAA', 'BBB', 'ccc', 1]
 *
 * @summary As per example, if a key is assigned a number value, this method will also returns it.
 *
 * Please filter it yourself to obtain pure string array. :)
 */
export const getEnumValueEntries: (e: EnumLike) => (string | number)[] = (e: EnumLike): (string | number)[] =>
  getEnumKeyEntries(e).map((key: string) => e[key]) as (string | number)[];
 
/**
 * Get all string element by removing all tag element in HTML string
 *
 * @param htmlString Target HTML string to retrieve only string element
 * @returns Array of string
 */
export const getHtmlContent = (htmlString: string): string[] => {
  const plaintText = htmlString.replace(/((\s+<|<)[^>]+>)|&[^;]+;/g, '~');
  const split = plaintText.split('~');
  const result = split.filter((el: string) => el !== '');
  return result;
};
 
/**
 * Convert pass-in HTML table formatted tooltip to a Map object with title map to value
 *
 * @param htmlTableFormattedTooltip Target GC Node tooltip which it html table formatted to be convert into Map object
 */
export const getValuePairsFromHtmlTable = (htmlTableFormattedTooltip: string): Map<string, string> => {
  const titleValuePairs: Map<string, string> = new Map();
  const trElements = findHtmlElementByTag(htmlTableFormattedTooltip, 'tr');
  if (trElements) {
    for (const trElement of trElements) {
      const trContents = getHtmlContent(trElement);
      let valueIndex: number;
 
      if (trContents.length > 0) {
        let indexOfSeperator = trContents.indexOf(':');
        if (indexOfSeperator === -1) {
          const seperator = trContents.filter((trContent: string) => trContent.includes(':'))[0];
          indexOfSeperator = trContents.indexOf(seperator) + 1;
          valueIndex = indexOfSeperator;
        } else {
          valueIndex = indexOfSeperator + 1;
        }
        const title = trContents.slice(0, indexOfSeperator).join('').trim().replace(':', '');
        const value = trContents.slice(valueIndex).join('').trim();
        titleValuePairs.set(title, value);
      }
    }
  }
  return titleValuePairs;
};
 
/**
 * Get key-value pairs from a HTML table formatted tooltip
 *
 * @param tooltip Target GC Node tooltip with HTML table formatted
 */
export const getTooltipValuePairs = (tooltip: string): Map<string, string> => {
  const trElements = findHtmlElementByTag(tooltip, 'tr');
  const keyValuePairs: Map<string, string> = new Map();
  if (trElements) {
    for (const trElement of trElements) {
      const rowContents = getHtmlContent(trElement);
      if (rowContents.length > 0) {
        const title = rowContents[0].replace(':', '');
        const value = rowContents.length === 2 ? rowContents[1] : '';
        keyValuePairs.set(title, value);
      }
    }
  }
  return keyValuePairs;
};
 
export const lowercaseFirstLetter = (value: string): string => value.charAt(0).toLowerCase() + value.slice(1);
 
export enum ActionTriggerType {
  Button,
  ContextMenu,
  Key,
}
 
/**
 * EnumLike interface that emulates an enumerator.
 */
export interface EnumLike {
  [key: number]: string | number;
}