@atlaskit/tokens 1.36.0 → 1.37.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/codemods/css-to-design-tokens/__tests__/css-to-design-tokens.test.tsx +489 -0
  3. package/codemods/css-to-design-tokens/__tests__/utils.test.tsx +145 -0
  4. package/codemods/css-to-design-tokens/lib/colors.tsx +71 -0
  5. package/codemods/css-to-design-tokens/lib/declaration.tsx +43 -0
  6. package/codemods/css-to-design-tokens/lib/legacy-colors.tsx +336 -0
  7. package/codemods/css-to-design-tokens/lib/meta.tsx +173 -0
  8. package/codemods/css-to-design-tokens/lib/tokens.tsx +54 -0
  9. package/codemods/css-to-design-tokens/lib/value.tsx +85 -0
  10. package/codemods/css-to-design-tokens/transform.tsx +99 -0
  11. package/codemods/hypermod.config.tsx +9 -0
  12. package/codemods/theme-to-design-tokens/__tests__/theme-to-design-tokens.test.tsx +1104 -0
  13. package/codemods/theme-to-design-tokens/transform.tsx +628 -0
  14. package/codemods/theme-to-design-tokens/utils/ast-meta.tsx +159 -0
  15. package/codemods/theme-to-design-tokens/utils/ast.tsx +46 -0
  16. package/codemods/theme-to-design-tokens/utils/color.tsx +45 -0
  17. package/codemods/theme-to-design-tokens/utils/css-utils.tsx +38 -0
  18. package/codemods/theme-to-design-tokens/utils/fuzzy-search.tsx +326 -0
  19. package/codemods/theme-to-design-tokens/utils/legacy-colors.tsx +232 -0
  20. package/codemods/theme-to-design-tokens/utils/named-colors.tsx +150 -0
  21. package/codemods/theme-to-design-tokens/utils/string-utils.tsx +22 -0
  22. package/codemods/utils/tokens.tsx +376 -0
  23. package/dist/cjs/artifacts/palettes-raw/typography-palette.js +3 -3
  24. package/dist/cjs/artifacts/themes/atlassian-typography-adg3.js +2 -2
  25. package/dist/cjs/artifacts/themes/atlassian-typography-minor3.js +2 -2
  26. package/dist/cjs/artifacts/token-default-values.js +15 -15
  27. package/dist/cjs/artifacts/tokens-raw/atlassian-typography-adg3.js +15 -15
  28. package/dist/cjs/artifacts/tokens-raw/atlassian-typography-minor3.js +16 -16
  29. package/dist/cjs/get-token-value.js +1 -1
  30. package/dist/cjs/get-token.js +1 -1
  31. package/dist/es2019/artifacts/palettes-raw/typography-palette.js +3 -3
  32. package/dist/es2019/artifacts/themes/atlassian-typography-adg3.js +15 -15
  33. package/dist/es2019/artifacts/themes/atlassian-typography-minor3.js +20 -20
  34. package/dist/es2019/artifacts/token-default-values.js +15 -15
  35. package/dist/es2019/artifacts/tokens-raw/atlassian-typography-adg3.js +15 -15
  36. package/dist/es2019/artifacts/tokens-raw/atlassian-typography-minor3.js +16 -16
  37. package/dist/es2019/get-token-value.js +1 -1
  38. package/dist/es2019/get-token.js +1 -1
  39. package/dist/esm/artifacts/palettes-raw/typography-palette.js +3 -3
  40. package/dist/esm/artifacts/themes/atlassian-typography-adg3.js +2 -2
  41. package/dist/esm/artifacts/themes/atlassian-typography-minor3.js +2 -2
  42. package/dist/esm/artifacts/token-default-values.js +15 -15
  43. package/dist/esm/artifacts/tokens-raw/atlassian-typography-adg3.js +15 -15
  44. package/dist/esm/artifacts/tokens-raw/atlassian-typography-minor3.js +16 -16
  45. package/dist/esm/get-token-value.js +1 -1
  46. package/dist/esm/get-token.js +1 -1
  47. package/dist/types/artifacts/palettes-raw/typography-palette.d.ts +1 -1
  48. package/dist/types/artifacts/themes/atlassian-typography-adg3.d.ts +2 -2
  49. package/dist/types/artifacts/themes/atlassian-typography-minor3.d.ts +2 -2
  50. package/dist/types/artifacts/token-default-values.d.ts +15 -15
  51. package/dist/types/artifacts/tokens-raw/atlassian-typography-adg3.d.ts +1 -1
  52. package/dist/types/artifacts/tokens-raw/atlassian-typography-minor3.d.ts +1 -1
  53. package/dist/types-ts4.5/artifacts/palettes-raw/typography-palette.d.ts +1 -1
  54. package/dist/types-ts4.5/artifacts/themes/atlassian-typography-adg3.d.ts +2 -2
  55. package/dist/types-ts4.5/artifacts/themes/atlassian-typography-minor3.d.ts +2 -2
  56. package/dist/types-ts4.5/artifacts/token-default-values.d.ts +15 -15
  57. package/dist/types-ts4.5/artifacts/tokens-raw/atlassian-typography-adg3.d.ts +1 -1
  58. package/dist/types-ts4.5/artifacts/tokens-raw/atlassian-typography-minor3.d.ts +1 -1
  59. package/package.json +5 -1
@@ -0,0 +1,159 @@
1
+ import type core from 'jscodeshift';
2
+
3
+ import { uniqueWordsFromTokens } from '../../utils/tokens';
4
+
5
+ import { getClosestDecendantOfType } from './ast';
6
+
7
+ export function getMetaFromAncestors(
8
+ j: core.JSCodeshift,
9
+ path: any,
10
+ meta: string[] = [],
11
+ ): string[] {
12
+ const parent = path.parentPath;
13
+ const grandParent = parent && parent.parentPath;
14
+
15
+ if (parent && parent.value.type === 'ObjectProperty') {
16
+ let value = '';
17
+
18
+ if (
19
+ parent.value.key.type === 'Literal' ||
20
+ parent.value.key.type === 'StringLiteral' ||
21
+ parent.value.key.type === 'NumericLiteral'
22
+ ) {
23
+ value = parent.value.key.value.toString();
24
+ } else {
25
+ value = parent.value.key.name;
26
+ }
27
+
28
+ meta.push(value);
29
+ }
30
+
31
+ if (parent && grandParent && grandParent.value.type === 'TemplateLiteral') {
32
+ const expressionIndex = grandParent.value.expressions.findIndex(
33
+ (exp: any) => exp.name === path.value.name,
34
+ );
35
+ const quasi = grandParent.value.quasis[expressionIndex];
36
+ const propertyName = (quasi.value.cooked || quasi.value.raw || '')
37
+ .replace(/\n/g, '')
38
+ .split(/;|{|}/)
39
+ .filter((el: string) => !el.match(/\.|\@|\(|\)/))
40
+ .pop()
41
+ .split(/:/g)[0]
42
+ .trim();
43
+
44
+ grandParent.value.quasis
45
+ .slice(0, expressionIndex + 1)
46
+ .map((q: any) => q.value.cooked)
47
+ // We reverse so the most nested one is first which we're more likely than not interested in
48
+ .reverse()
49
+ .some((str: string) => {
50
+ const result = /(hover|active|disabled|focus)/.exec(str.toLowerCase());
51
+
52
+ if (result) {
53
+ meta.push(result[0]);
54
+ return true;
55
+ }
56
+ });
57
+
58
+ meta.push(propertyName);
59
+ }
60
+
61
+ if (parent && parent.value.type === 'JSXAttribute') {
62
+ if (
63
+ !['css', 'styles', 'style', 'fill', 'stopColor', 'startColor'].includes(
64
+ parent.value.name.name,
65
+ )
66
+ ) {
67
+ meta.push(parent.value.name.name);
68
+ }
69
+ }
70
+
71
+ const closestJSXElement = getClosestDecendantOfType(
72
+ j,
73
+ path,
74
+ j.JSXOpeningElement,
75
+ );
76
+
77
+ if (closestJSXElement) {
78
+ const jsxElementName = closestJSXElement.value.name.name;
79
+ const nameComponents = jsxElementName
80
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
81
+ .split(' ');
82
+
83
+ meta.push(...nameComponents);
84
+ }
85
+
86
+ if (parent && parent.value.type === 'VariableDeclarator') {
87
+ meta.push(parent.value.id.name);
88
+ }
89
+
90
+ if (parent) {
91
+ return getMetaFromAncestors(j, parent, meta);
92
+ }
93
+
94
+ return meta;
95
+ }
96
+
97
+ export function cleanMeta(meta: string[]) {
98
+ return meta
99
+ .reduce<string[]>(
100
+ (accum, val) => [
101
+ ...accum,
102
+ ...(typeof val === 'string'
103
+ ? val.split(/(?=[A-Z])/g).map((e) => e.toLowerCase())
104
+ : []),
105
+ ],
106
+ [],
107
+ )
108
+ .reduce<string[]>((accum, val) => {
109
+ const cleanVal = val
110
+ .replace(/:/g, '')
111
+ .replace(/,/g, '')
112
+ .replace('grey', 'neutral')
113
+ .replace('skeleton', 'neutral')
114
+ .replace('texts', 'text')
115
+ .replace('red', 'danger')
116
+ .replace('error', 'danger')
117
+ .replace('invalid', 'danger')
118
+ .replace('removed', 'danger')
119
+ .replace('removal', 'danger')
120
+ .replace('remove', 'danger')
121
+ .replace('focus', 'focused')
122
+ .replace('valid', 'success')
123
+ .replace('successful', 'success')
124
+ .replace('risk', 'warning')
125
+ .replace('caution', 'warning')
126
+ .replace('primary', 'bold')
127
+ .replace('secondary', 'subtle')
128
+ .replace('hyperlink', 'link')
129
+ .replace('anchor', 'link')
130
+ .replace('active', 'pressed')
131
+ .replace('hover', 'hovered')
132
+ .replace('card', 'raised')
133
+ .replace('dragged', 'surface overlay')
134
+ .replace('dragging', 'surface overlay')
135
+ .replace('drag', 'surface overlay')
136
+ .replace('background-color', 'background')
137
+ .replace('color', 'text')
138
+ .replace('icons', 'icon')
139
+ .replace('glyph', 'icon')
140
+ .replace('stroke', 'border')
141
+ .replace('border-left', 'border')
142
+ .replace('border-right', 'border')
143
+ .replace('border-top', 'border')
144
+ .replace('border-bottom', 'border')
145
+ .replace('box-shadow', 'shadow');
146
+
147
+ accum.push(...cleanVal.split(' '));
148
+
149
+ return accum;
150
+ }, [])
151
+ .filter((val) => uniqueWordsFromTokens.includes(val))
152
+ .reduce<string[]>((accum, val) => {
153
+ if (!accum.includes(val)) {
154
+ accum.push(val);
155
+ }
156
+
157
+ return accum;
158
+ }, []);
159
+ }
@@ -0,0 +1,46 @@
1
+ import { isDecendantOfType } from '@hypermod/utils';
2
+ import type { ASTNode, ASTPath, JSCodeshift } from 'jscodeshift';
3
+
4
+ export function isDecendantOfToken(
5
+ j: JSCodeshift,
6
+ path: ASTPath | ASTNode,
7
+ ): boolean {
8
+ if (
9
+ 'type' in path &&
10
+ path.type === 'CallExpression' &&
11
+ path.callee.type === 'Identifier' &&
12
+ path.callee.name === 'token'
13
+ ) {
14
+ return true;
15
+ }
16
+
17
+ return (
18
+ j(path).closest(j.CallExpression, { callee: { name: 'token' } }).length > 0
19
+ );
20
+ }
21
+
22
+ export function isParentOfToken(j: JSCodeshift, path: any): boolean {
23
+ if (
24
+ path.type === 'CallExpression' &&
25
+ path.callee.type === 'Identifier' &&
26
+ path.callee.name === 'token'
27
+ ) {
28
+ return true;
29
+ }
30
+
31
+ return (
32
+ j(path).find(j.CallExpression, { callee: { name: 'token' } }).length > 0
33
+ );
34
+ }
35
+
36
+ export function getClosestDecendantOfType(
37
+ j: JSCodeshift,
38
+ path: ASTPath<any>,
39
+ type: any,
40
+ ) {
41
+ if (!isDecendantOfType(j, path, type)) {
42
+ return;
43
+ }
44
+
45
+ return j(path).closest(type).get();
46
+ }
@@ -0,0 +1,45 @@
1
+ import { legacyColorMixins, legacyColors } from './legacy-colors';
2
+ import { namedColors } from './named-colors';
3
+
4
+ export const isLegacyColor = (value: string) => legacyColors.includes(value);
5
+
6
+ export const isLegacyNamedColor = (value: string) =>
7
+ legacyColorMixins.includes(value);
8
+
9
+ const colorRegexp =
10
+ /#(?:[a-f0-9]{3}|[a-f0-9]{6}|[a-f0-9]{8})\b|(?:rgb|rgba|hsl|hsla|lch|lab|color)\([^\)]*\)/;
11
+
12
+ export const includesHardCodedColor = (raw: string) => {
13
+ const value = raw.toLowerCase();
14
+ if (colorRegexp.exec(value)) {
15
+ return true;
16
+ }
17
+
18
+ for (let i = 0; i < namedColors.length; i++) {
19
+ if (value.includes(`${namedColors[i]};`)) {
20
+ return true;
21
+ }
22
+ }
23
+
24
+ return false;
25
+ };
26
+
27
+ export const isHardCodedColor = (raw: string) => {
28
+ const value = raw.toLowerCase();
29
+
30
+ if (namedColors.includes(value)) {
31
+ return true;
32
+ }
33
+
34
+ const match = value.toLowerCase().match(colorRegexp);
35
+ if (match && match[0] === value) {
36
+ return true;
37
+ }
38
+
39
+ return false;
40
+ };
41
+
42
+ export function isBoldColor(color: string) {
43
+ const number = parseInt(color.replace(/^./, ''), 10);
44
+ return number > 300;
45
+ }
@@ -0,0 +1,38 @@
1
+ import { isColorRelatedProperty } from '../../css-to-design-tokens/lib/declaration';
2
+
3
+ export function containsReplaceableCSSDeclarations(input: string) {
4
+ const cssPattern = /(\S+)\s*:/g;
5
+
6
+ let match;
7
+ while ((match = cssPattern.exec(input)) !== null) {
8
+ if (isColorRelatedProperty(match[1])) {
9
+ return true;
10
+ }
11
+ }
12
+ return false;
13
+ }
14
+
15
+ export function findEndIndexOfCSSExpression(
16
+ text: string,
17
+ isAtEndOfInput: boolean,
18
+ ): number | null {
19
+ // CSS expression can end *on* a semicolon or *before* a brace. In either
20
+ // case we treat the remaining part of the value to cover one character
21
+ // before that symbol.
22
+ const semicolonIndex = text.indexOf(';');
23
+ const braceIndex = text.indexOf('}');
24
+
25
+ if (semicolonIndex === -1 && braceIndex === -1) {
26
+ if (isAtEndOfInput) {
27
+ return text.length;
28
+ } else {
29
+ return null;
30
+ }
31
+ } else if (semicolonIndex === -1) {
32
+ return braceIndex - 1;
33
+ } else if (braceIndex === -1) {
34
+ return semicolonIndex - 1;
35
+ } else {
36
+ return Math.min(semicolonIndex, braceIndex) - 1;
37
+ }
38
+ }
@@ -0,0 +1,326 @@
1
+ /* eslint-disable */
2
+
3
+ /**
4
+ * Fuzzy search ripped from the internet.
5
+ */
6
+ const FuzzySet = function (
7
+ arr: string[] = [],
8
+ useLevenshtein?: boolean,
9
+ gramSizeLower: number = 2,
10
+ gramSizeUpper: number = 3,
11
+ ) {
12
+ var fuzzyset: any = {
13
+ gramSizeLower: gramSizeLower,
14
+ gramSizeUpper: gramSizeUpper,
15
+ useLevenshtein: typeof useLevenshtein !== 'boolean' ? true : useLevenshtein,
16
+ exactSet: {},
17
+ matchDict: {},
18
+ items: {},
19
+ };
20
+
21
+ var levenshtein = function (str1: string, str2: string) {
22
+ var current: number[] = [];
23
+ var prev: number;
24
+ var value: number;
25
+
26
+ for (var i = 0; i <= str2.length; i++) {
27
+ for (var j = 0; j <= str1.length; j++) {
28
+ if (i && j) {
29
+ if (str1.charAt(j - 1) === str2.charAt(i - 1)) {
30
+ // @ts-expect-error
31
+ value = prev;
32
+ } else {
33
+ // @ts-expect-error
34
+ value = Math.min(current[j], current[j - 1], prev) + 1;
35
+ }
36
+ } else {
37
+ value = i + j;
38
+ }
39
+
40
+ prev = current[j];
41
+ current[j] = value;
42
+ }
43
+ }
44
+
45
+ return current.pop() as number;
46
+ };
47
+
48
+ // return an edit distance from 0 to 1
49
+ var _distance = function (str1: string, str2: string) {
50
+ if (str1 === null && str2 === null) {
51
+ throw new Error('Trying to compare two null values');
52
+ }
53
+ if (str1 === null || str2 === null) {
54
+ return 0;
55
+ }
56
+ str1 = String(str1);
57
+ str2 = String(str2);
58
+
59
+ var distance = levenshtein(str1, str2);
60
+ if (str1.length > str2.length) {
61
+ return 1 - distance / str1.length;
62
+ } else {
63
+ return 1 - distance / str2.length;
64
+ }
65
+ };
66
+ var _nonWordRe = /[^a-zA-Z0-9\u00C0-\u00FF, ]+/g;
67
+
68
+ var _iterateGrams = function (value: any, gramSize: any) {
69
+ gramSize = gramSize || 2;
70
+ var simplified = '-' + value.toLowerCase().replace(_nonWordRe, '') + '-',
71
+ lenDiff = gramSize - simplified.length,
72
+ results = [];
73
+ if (lenDiff > 0) {
74
+ for (var i = 0; i < lenDiff; ++i) {
75
+ simplified += '-';
76
+ }
77
+ }
78
+ for (var i = 0; i < simplified.length - gramSize + 1; ++i) {
79
+ results.push(simplified.slice(i, i + gramSize));
80
+ }
81
+ return results;
82
+ };
83
+
84
+ var _gramCounter = function (value: string, gramSize: number) {
85
+ // return an object where key=gram, value=number of occurrences
86
+ gramSize = gramSize || 2;
87
+ var result = {},
88
+ grams = _iterateGrams(value, gramSize),
89
+ i = 0;
90
+ for (i; i < grams.length; ++i) {
91
+ if (grams[i] in result) {
92
+ // @ts-expect-error
93
+ result[grams[i]] += 1;
94
+ } else {
95
+ // @ts-expect-error
96
+ result[grams[i]] = 1;
97
+ }
98
+ }
99
+ return result;
100
+ };
101
+
102
+ // the main functions
103
+ fuzzyset.get = function (
104
+ value: string,
105
+ defaultValue: string,
106
+ minMatchScore: number,
107
+ ) {
108
+ // check for value in set, returning defaultValue or null if none found
109
+ if (minMatchScore === undefined) {
110
+ minMatchScore = 0.33;
111
+ }
112
+ var result = this._get(value, minMatchScore);
113
+ if (!result && typeof defaultValue !== 'undefined') {
114
+ return defaultValue;
115
+ }
116
+ return result;
117
+ };
118
+
119
+ fuzzyset._get = function (value: string, minMatchScore: number) {
120
+ var results = [];
121
+ // start with high gram size and if there are no results, go to lower gram sizes
122
+ for (
123
+ var gramSize = this.gramSizeUpper;
124
+ gramSize >= this.gramSizeLower;
125
+ --gramSize
126
+ ) {
127
+ results = this.__get(value, gramSize, minMatchScore);
128
+ if (results && results.length > 0) {
129
+ return results;
130
+ }
131
+ }
132
+ return null;
133
+ };
134
+
135
+ fuzzyset.__get = function (
136
+ value: string,
137
+ gramSize: number,
138
+ minMatchScore: number,
139
+ ) {
140
+ var normalizedValue = this._normalizeStr(value),
141
+ matches = {},
142
+ gramCounts = _gramCounter(normalizedValue, gramSize),
143
+ items = this.items[gramSize],
144
+ sumOfSquareGramCounts = 0,
145
+ gram,
146
+ gramCount,
147
+ i,
148
+ index,
149
+ otherGramCount;
150
+
151
+ for (gram in gramCounts) {
152
+ // @ts-expect-error
153
+ gramCount = gramCounts[gram];
154
+ sumOfSquareGramCounts += Math.pow(gramCount, 2);
155
+ if (gram in this.matchDict) {
156
+ for (i = 0; i < this.matchDict[gram].length; ++i) {
157
+ index = this.matchDict[gram][i][0];
158
+ otherGramCount = this.matchDict[gram][i][1];
159
+ if (index in matches) {
160
+ // @ts-expect-error
161
+ matches[index] += gramCount * otherGramCount;
162
+ } else {
163
+ // @ts-expect-error
164
+ matches[index] = gramCount * otherGramCount;
165
+ }
166
+ }
167
+ }
168
+ }
169
+
170
+ function isEmptyObject(obj: any) {
171
+ for (var prop in obj) {
172
+ if (obj.hasOwnProperty(prop)) {
173
+ return false;
174
+ }
175
+ }
176
+ return true;
177
+ }
178
+
179
+ if (isEmptyObject(matches)) {
180
+ return null;
181
+ }
182
+
183
+ var vectorNormal = Math.sqrt(sumOfSquareGramCounts),
184
+ results: string[] = [],
185
+ matchScore;
186
+ // build a results list of [score, str]
187
+ for (var matchIndex in matches) {
188
+ // @ts-expect-error
189
+ matchScore = matches[matchIndex];
190
+ // @ts-expect-error
191
+ results.push([
192
+ matchScore / (vectorNormal * items[matchIndex][0]),
193
+ items[matchIndex][1],
194
+ ]);
195
+ }
196
+ var sortDescending = function (a: any, b: any) {
197
+ if (a[0] < b[0]) {
198
+ return 1;
199
+ } else if (a[0] > b[0]) {
200
+ return -1;
201
+ } else {
202
+ return 0;
203
+ }
204
+ };
205
+ results.sort(sortDescending);
206
+ if (this.useLevenshtein) {
207
+ var newResults: string[] = [],
208
+ endIndex = Math.min(50, results.length);
209
+ // truncate somewhat arbitrarily to 50
210
+ // @ts-expect-error
211
+ for (var i = 0; i < endIndex; ++i) {
212
+ // @ts-expect-error
213
+ newResults.push([
214
+ _distance(results[i][1], normalizedValue),
215
+ results[i][1],
216
+ ]);
217
+ }
218
+ results = newResults;
219
+ results.sort(sortDescending);
220
+ }
221
+ newResults = [];
222
+ results.forEach(
223
+ function (scoreWordPair: any) {
224
+ if (scoreWordPair[0] >= minMatchScore) {
225
+ // @ts-expect-error
226
+ newResults.push([scoreWordPair[0], this.exactSet[scoreWordPair[1]]]);
227
+ }
228
+ }.bind(this),
229
+ );
230
+ return newResults;
231
+ };
232
+
233
+ fuzzyset.add = function (value: any) {
234
+ var normalizedValue = this._normalizeStr(value);
235
+ if (normalizedValue in this.exactSet) {
236
+ return false;
237
+ }
238
+
239
+ var i = this.gramSizeLower;
240
+ for (i; i < this.gramSizeUpper + 1; ++i) {
241
+ this._add(value, i);
242
+ }
243
+ };
244
+
245
+ fuzzyset._add = function (value: string, gramSize: number) {
246
+ var normalizedValue = this._normalizeStr(value),
247
+ items = this.items[gramSize] || [],
248
+ index = items.length;
249
+
250
+ items.push(0);
251
+ var gramCounts = _gramCounter(normalizedValue, gramSize);
252
+ var sumOfSquareGramCounts = 0;
253
+ var gram: string;
254
+ var gramCount: number;
255
+
256
+ for (gram in gramCounts) {
257
+ // @ts-expect-error
258
+ gramCount = gramCounts[gram];
259
+ sumOfSquareGramCounts += Math.pow(gramCount, 2);
260
+ if (gram in this.matchDict) {
261
+ this.matchDict[gram].push([index, gramCount]);
262
+ } else {
263
+ this.matchDict[gram] = [[index, gramCount]];
264
+ }
265
+ }
266
+ var vectorNormal = Math.sqrt(sumOfSquareGramCounts);
267
+ items[index] = [vectorNormal, normalizedValue];
268
+ this.items[gramSize] = items;
269
+ this.exactSet[normalizedValue] = value;
270
+ };
271
+
272
+ fuzzyset._normalizeStr = function (str: string) {
273
+ if (Object.prototype.toString.call(str) !== '[object String]') {
274
+ throw new Error('Must use a string as argument to FuzzySet functions');
275
+ }
276
+ return str.toLowerCase();
277
+ };
278
+
279
+ // return length of items in set
280
+ fuzzyset.length = function () {
281
+ var count = 0,
282
+ prop;
283
+ for (prop in this.exactSet) {
284
+ if (this.exactSet.hasOwnProperty(prop)) {
285
+ count += 1;
286
+ }
287
+ }
288
+ return count;
289
+ };
290
+
291
+ // return is set is empty
292
+ fuzzyset.isEmpty = function () {
293
+ for (var prop in this.exactSet) {
294
+ if (this.exactSet.hasOwnProperty(prop)) {
295
+ return false;
296
+ }
297
+ }
298
+ return true;
299
+ };
300
+
301
+ // return list of values loaded into set
302
+ fuzzyset.values = function () {
303
+ var values = [],
304
+ prop;
305
+ for (prop in this.exactSet) {
306
+ if (this.exactSet.hasOwnProperty(prop)) {
307
+ values.push(this.exactSet[prop]);
308
+ }
309
+ }
310
+ return values;
311
+ };
312
+
313
+ // initialization
314
+ var i = fuzzyset.gramSizeLower;
315
+ for (i; i < fuzzyset.gramSizeUpper + 1; ++i) {
316
+ fuzzyset.items[i] = [];
317
+ }
318
+ // add all the items to the set
319
+ for (i = 0; i < arr.length; ++i) {
320
+ fuzzyset.add(arr[i]);
321
+ }
322
+
323
+ return fuzzyset;
324
+ };
325
+
326
+ export default FuzzySet;