@supericons/mcp 0.4.9 → 0.4.11
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.
- package/CHANGELOG.md +18 -0
- package/generated/motion-lab-baseline.json +1 -1
- package/hosted-search-client.js +23 -8
- package/index.js +18 -17
- package/package.json +4 -3
- package/public/product-facts.json +8 -8
- package/recommend-icons.js +1429 -1299
- package/remote-server.js +23 -7
- package/runtime/icon-taxonomy-seed.js +30 -2
- package/runtime/supericons-ai-taxonomy.js +403 -0
- package/search.js +98 -32
- package/semantic-registry.js +177 -56
- package/server.json +2 -2
package/recommend-icons.js
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
buildPublicSemanticPayload,
|
|
3
|
-
getSemanticRecordForIcon,
|
|
4
|
-
scoreSemanticAlignment,
|
|
5
|
-
} from './semantic-registry.js';
|
|
6
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
7
|
-
import { dirname, join } from 'node:path';
|
|
8
|
-
import { fileURLToPath } from 'node:url';
|
|
9
|
-
import {
|
|
10
|
-
expandCjkQuery,
|
|
11
|
-
normalizeCjkSearchText,
|
|
12
|
-
} from './runtime/cjk-search-core.js';
|
|
13
|
-
import {
|
|
14
|
-
buildIntentQueryVariants,
|
|
15
|
-
buildSearchIntentProfile,
|
|
16
|
-
getIntentCandidateAdjustment,
|
|
17
|
-
} from './runtime/search-intent-core.js';
|
|
18
|
-
|
|
19
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
|
-
const cjkTermsPath = join(__dirname, 'public', 'cjk-search-terms.json');
|
|
21
|
-
const multilingualAliasesPath = join(__dirname, 'public', 'multilingual-search-aliases.json');
|
|
22
|
-
const cjkSearchTerms = existsSync(cjkTermsPath)
|
|
23
|
-
? JSON.parse(readFileSync(cjkTermsPath, 'utf8')).terms || []
|
|
24
|
-
: [];
|
|
25
|
-
const multilingualSearchAliases = existsSync(multilingualAliasesPath)
|
|
26
|
-
? JSON.parse(readFileSync(multilingualAliasesPath, 'utf8')).aliases || []
|
|
27
|
-
: [];
|
|
28
|
-
const multilingualExpansionTerms = [...cjkSearchTerms, ...multilingualSearchAliases];
|
|
29
|
-
const SLOT_SEARCH_CONCURRENCY = 2;
|
|
30
|
-
const SLOT_QUERY_CONCURRENCY = 1;
|
|
31
|
-
|
|
32
|
-
const GENERIC_SLOT_WORDS = new Set([
|
|
33
|
-
'action',
|
|
34
|
-
'button',
|
|
1
|
+
import {
|
|
2
|
+
buildPublicSemanticPayload,
|
|
3
|
+
getSemanticRecordForIcon,
|
|
4
|
+
scoreSemanticAlignment,
|
|
5
|
+
} from './semantic-registry.js';
|
|
6
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import {
|
|
10
|
+
expandCjkQuery,
|
|
11
|
+
normalizeCjkSearchText,
|
|
12
|
+
} from './runtime/cjk-search-core.js';
|
|
13
|
+
import {
|
|
14
|
+
buildIntentQueryVariants,
|
|
15
|
+
buildSearchIntentProfile,
|
|
16
|
+
getIntentCandidateAdjustment,
|
|
17
|
+
} from './runtime/search-intent-core.js';
|
|
18
|
+
|
|
19
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const cjkTermsPath = join(__dirname, 'public', 'cjk-search-terms.json');
|
|
21
|
+
const multilingualAliasesPath = join(__dirname, 'public', 'multilingual-search-aliases.json');
|
|
22
|
+
const cjkSearchTerms = existsSync(cjkTermsPath)
|
|
23
|
+
? JSON.parse(readFileSync(cjkTermsPath, 'utf8')).terms || []
|
|
24
|
+
: [];
|
|
25
|
+
const multilingualSearchAliases = existsSync(multilingualAliasesPath)
|
|
26
|
+
? JSON.parse(readFileSync(multilingualAliasesPath, 'utf8')).aliases || []
|
|
27
|
+
: [];
|
|
28
|
+
const multilingualExpansionTerms = [...cjkSearchTerms, ...multilingualSearchAliases];
|
|
29
|
+
const SLOT_SEARCH_CONCURRENCY = 2;
|
|
30
|
+
const SLOT_QUERY_CONCURRENCY = 1;
|
|
31
|
+
|
|
32
|
+
const GENERIC_SLOT_WORDS = new Set([
|
|
33
|
+
'action',
|
|
34
|
+
'button',
|
|
35
35
|
'buttons',
|
|
36
36
|
'control',
|
|
37
37
|
'controls',
|
|
@@ -45,325 +45,348 @@ const GENERIC_SLOT_WORDS = new Set([
|
|
|
45
45
|
'tab',
|
|
46
46
|
'tabs',
|
|
47
47
|
'ui',
|
|
48
|
-
'view',
|
|
49
|
-
]);
|
|
50
|
-
|
|
51
|
-
const VARIANT_PENALTIES = Object.freeze([
|
|
52
|
-
{ token: 'circle', pattern: /circle/i, penalty: 12 },
|
|
53
|
-
{ token: 'square', pattern: /square/i, penalty: 12 },
|
|
54
|
-
{ token: 'dash', pattern: /dash/i, penalty: 5 },
|
|
55
|
-
{ token: 'badge', pattern: /badge/i, penalty: 4 },
|
|
56
|
-
{ token: 'brand', pattern: /\bbrand\b/i, penalty: 30 },
|
|
57
|
-
{ token: 'off', pattern: /\boff\b/i, penalty: 18 },
|
|
58
|
-
{ token: 'slash', pattern: /slash/i, penalty: 8 },
|
|
59
|
-
{ token: 'warning', pattern: /warning/i, penalty: 5 },
|
|
60
|
-
{ token: 'ai', pattern: /\bai\b/i, penalty: 18 },
|
|
61
|
-
{ token: 'add', pattern: /\badd\b/i, penalty: 12 },
|
|
62
|
-
{ token: 'plus', pattern: /\bplus\b/i, penalty: 18 },
|
|
63
|
-
{ token: 'edit', pattern: /\bedit\b/i, penalty: 12 },
|
|
64
|
-
{ token: 'remove', pattern: /\bremove\b/i, penalty: 12 },
|
|
65
|
-
{ token: 'delete', pattern: /\bdelete\b/i, penalty: 12 },
|
|
66
|
-
{ token: 'minus', pattern: /\bminus\b/i, penalty: 24 },
|
|
67
|
-
{ token: 'cancel', pattern: /\bcancel\b/i, penalty: 30 },
|
|
68
|
-
{ token: 'x', pattern: /\bx\b/i, penalty: 30 },
|
|
69
|
-
{ token: 'exclamation', pattern: /\bexclamation\b/i, penalty: 24 },
|
|
70
|
-
{ token: 'discount', pattern: /\bdiscount\b/i, penalty: 24 },
|
|
71
|
-
{ token: 'heart', pattern: /\bheart\b/i, penalty: 18 },
|
|
72
|
-
{ token: 'zap', pattern: /\bzap\b/i, penalty: 30 },
|
|
73
|
-
{ token: 'bolt', pattern: /\bbolt\b/i, penalty: 18 },
|
|
74
|
-
{ token: 'wifi', pattern: /\bwifi\b/i, penalty: 12 },
|
|
75
|
-
{ token: 'align', pattern: /\balign\b/i, penalty: 12 },
|
|
76
|
-
{ token: 'fruit', pattern: /\bfruit\b/i, penalty: 12 },
|
|
77
|
-
{ token: 'open', pattern: /\bopen\b/i, penalty: 28 },
|
|
78
|
-
{ token: 'unlock', pattern: /\bunlock(?:ed)?\b/i, penalty: 28 },
|
|
79
|
-
{ token: 'ban', pattern: /\bban\b/i, penalty: 24 },
|
|
80
|
-
{ token: 'blocked', pattern: /\bblocked\b/i, penalty: 24 },
|
|
81
|
-
{ token: 'rupee', pattern: /\brupee\b/i, penalty: 18 },
|
|
82
|
-
{ token: 'ruble', pattern: /\bruble\b/i, penalty: 18 },
|
|
83
|
-
{ token: 'franc', pattern: /\bfranc\b/i, penalty: 18 },
|
|
84
|
-
{ token: 'lira', pattern: /\blira\b/i, penalty: 18 },
|
|
85
|
-
{ token: 'bitcoin', pattern: /\bbitcoin\b/i, penalty: 18 },
|
|
86
|
-
{ token: 'dollar', pattern: /\bdollar\b/i, penalty: 18 },
|
|
87
|
-
{ token: 'cent', pattern: /\bcent\b/i, penalty: 18 },
|
|
88
|
-
{ token: 'yen', pattern: /\byen\b/i, penalty: 18 },
|
|
89
|
-
{ token: 'yuan', pattern: /\byuan\b/i, penalty: 18 },
|
|
90
|
-
{ token: 'euro', pattern: /\beuro\b/i, penalty: 18 },
|
|
91
|
-
{ token: 'pound', pattern: /\bpound\b/i, penalty: 18 },
|
|
92
|
-
{ token: 'down', pattern: /\bdown\b/i, penalty: 8 },
|
|
93
|
-
{ token: 'left', pattern: /\bleft\b/i, penalty: 8 },
|
|
94
|
-
{ token: 'up', pattern: /\bup\b/i, penalty: 8 },
|
|
95
|
-
{ token: 'corner', pattern: /\bcorner\b/i, penalty: 12 },
|
|
96
|
-
{ token: 'break', pattern: /\bbreak\b/i, penalty: 18 },
|
|
97
|
-
{ token: 'broken', pattern: /\bbroken\b/i, penalty: 18 },
|
|
98
|
-
{ token: 'locked', pattern: /\blocked\b/i, penalty: 18 },
|
|
99
|
-
{ token: 'orange', pattern: /\borange\b/i, penalty: 12 },
|
|
48
|
+
'view',
|
|
100
49
|
]);
|
|
101
50
|
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
blocked: ['ban', 'banned', 'block', 'blocked'],
|
|
111
|
-
add: ['add', 'create', 'plus'],
|
|
112
|
-
plus: ['add', 'create', 'plus'],
|
|
113
|
-
edit: ['edit', 'editing', 'modify', 'pencil'],
|
|
114
|
-
remove: ['remove', 'removed', 'delete', 'minus'],
|
|
115
|
-
delete: ['delete', 'remove', 'trash'],
|
|
116
|
-
minus: ['minus', 'remove', 'removed', 'delete'],
|
|
117
|
-
cancel: ['cancel', 'canceled', 'cancelled', 'disabled', 'remove'],
|
|
118
|
-
x: ['x', 'close', 'remove', 'delete', 'blocked', 'broken', 'off'],
|
|
119
|
-
exclamation: ['alert', 'warning', 'exclamation'],
|
|
120
|
-
discount: ['discount', 'coupon', 'coupons', 'promo', 'promotion', 'deal'],
|
|
121
|
-
heart: ['heart', 'favorite', 'favourite', 'liked', 'wishlist'],
|
|
122
|
-
ai: ['ai', 'smart', 'assistant', 'automation'],
|
|
123
|
-
break: ['break', 'broken'],
|
|
124
|
-
broken: ['break', 'broken'],
|
|
125
|
-
locked: ['lock', 'locked', 'secure', 'security'],
|
|
126
|
-
ruble: ['ruble', 'rouble', 'rub'],
|
|
127
|
-
franc: ['franc', 'chf'],
|
|
128
|
-
lira: ['lira'],
|
|
129
|
-
bitcoin: ['bitcoin', 'btc'],
|
|
130
|
-
dollar: ['dollar', 'usd'],
|
|
131
|
-
yuan: ['yuan', 'cny'],
|
|
132
|
-
});
|
|
51
|
+
const BRAND_LOGO_WORDS = new Set([
|
|
52
|
+
'brand',
|
|
53
|
+
'brands',
|
|
54
|
+
'logo',
|
|
55
|
+
'logos',
|
|
56
|
+
'mark',
|
|
57
|
+
'wordmark',
|
|
58
|
+
]);
|
|
133
59
|
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
60
|
+
const BRAND_LOGO_GENERIC_WORDS = new Set([
|
|
61
|
+
...GENERIC_SLOT_WORDS,
|
|
62
|
+
...BRAND_LOGO_WORDS,
|
|
63
|
+
'app',
|
|
64
|
+
'application',
|
|
65
|
+
'company',
|
|
66
|
+
'hero',
|
|
67
|
+
'page',
|
|
68
|
+
'product',
|
|
69
|
+
'site',
|
|
70
|
+
'title',
|
|
71
|
+
'website',
|
|
143
72
|
]);
|
|
73
|
+
|
|
74
|
+
const VARIANT_PENALTIES = Object.freeze([
|
|
75
|
+
{ token: 'circle', pattern: /circle/i, penalty: 12 },
|
|
76
|
+
{ token: 'square', pattern: /square/i, penalty: 12 },
|
|
77
|
+
{ token: 'dash', pattern: /dash/i, penalty: 5 },
|
|
78
|
+
{ token: 'badge', pattern: /badge/i, penalty: 4 },
|
|
79
|
+
{ token: 'brand', pattern: /\bbrand\b/i, penalty: 30 },
|
|
80
|
+
{ token: 'off', pattern: /\boff\b/i, penalty: 18 },
|
|
81
|
+
{ token: 'slash', pattern: /slash/i, penalty: 8 },
|
|
82
|
+
{ token: 'warning', pattern: /warning/i, penalty: 5 },
|
|
83
|
+
{ token: 'ai', pattern: /\bai\b/i, penalty: 18 },
|
|
84
|
+
{ token: 'add', pattern: /\badd\b/i, penalty: 12 },
|
|
85
|
+
{ token: 'plus', pattern: /\bplus\b/i, penalty: 18 },
|
|
86
|
+
{ token: 'edit', pattern: /\bedit\b/i, penalty: 12 },
|
|
87
|
+
{ token: 'remove', pattern: /\bremove\b/i, penalty: 12 },
|
|
88
|
+
{ token: 'delete', pattern: /\bdelete\b/i, penalty: 12 },
|
|
89
|
+
{ token: 'minus', pattern: /\bminus\b/i, penalty: 24 },
|
|
90
|
+
{ token: 'cancel', pattern: /\bcancel\b/i, penalty: 30 },
|
|
91
|
+
{ token: 'x', pattern: /\bx\b/i, penalty: 30 },
|
|
92
|
+
{ token: 'exclamation', pattern: /\bexclamation\b/i, penalty: 24 },
|
|
93
|
+
{ token: 'discount', pattern: /\bdiscount\b/i, penalty: 24 },
|
|
94
|
+
{ token: 'heart', pattern: /\bheart\b/i, penalty: 18 },
|
|
95
|
+
{ token: 'zap', pattern: /\bzap\b/i, penalty: 30 },
|
|
96
|
+
{ token: 'bolt', pattern: /\bbolt\b/i, penalty: 18 },
|
|
97
|
+
{ token: 'wifi', pattern: /\bwifi\b/i, penalty: 12 },
|
|
98
|
+
{ token: 'align', pattern: /\balign\b/i, penalty: 12 },
|
|
99
|
+
{ token: 'fruit', pattern: /\bfruit\b/i, penalty: 12 },
|
|
100
|
+
{ token: 'open', pattern: /\bopen\b/i, penalty: 28 },
|
|
101
|
+
{ token: 'unlock', pattern: /\bunlock(?:ed)?\b/i, penalty: 28 },
|
|
102
|
+
{ token: 'ban', pattern: /\bban\b/i, penalty: 24 },
|
|
103
|
+
{ token: 'blocked', pattern: /\bblocked\b/i, penalty: 24 },
|
|
104
|
+
{ token: 'rupee', pattern: /\brupee\b/i, penalty: 18 },
|
|
105
|
+
{ token: 'ruble', pattern: /\bruble\b/i, penalty: 18 },
|
|
106
|
+
{ token: 'franc', pattern: /\bfranc\b/i, penalty: 18 },
|
|
107
|
+
{ token: 'lira', pattern: /\blira\b/i, penalty: 18 },
|
|
108
|
+
{ token: 'bitcoin', pattern: /\bbitcoin\b/i, penalty: 18 },
|
|
109
|
+
{ token: 'dollar', pattern: /\bdollar\b/i, penalty: 18 },
|
|
110
|
+
{ token: 'cent', pattern: /\bcent\b/i, penalty: 18 },
|
|
111
|
+
{ token: 'yen', pattern: /\byen\b/i, penalty: 18 },
|
|
112
|
+
{ token: 'yuan', pattern: /\byuan\b/i, penalty: 18 },
|
|
113
|
+
{ token: 'euro', pattern: /\beuro\b/i, penalty: 18 },
|
|
114
|
+
{ token: 'pound', pattern: /\bpound\b/i, penalty: 18 },
|
|
115
|
+
{ token: 'down', pattern: /\bdown\b/i, penalty: 8 },
|
|
116
|
+
{ token: 'left', pattern: /\bleft\b/i, penalty: 8 },
|
|
117
|
+
{ token: 'up', pattern: /\bup\b/i, penalty: 8 },
|
|
118
|
+
{ token: 'corner', pattern: /\bcorner\b/i, penalty: 12 },
|
|
119
|
+
{ token: 'break', pattern: /\bbreak\b/i, penalty: 18 },
|
|
120
|
+
{ token: 'broken', pattern: /\bbroken\b/i, penalty: 18 },
|
|
121
|
+
{ token: 'locked', pattern: /\blocked\b/i, penalty: 18 },
|
|
122
|
+
{ token: 'orange', pattern: /\borange\b/i, penalty: 12 },
|
|
123
|
+
]);
|
|
124
|
+
|
|
125
|
+
const VARIANT_TOKENS = new Set(VARIANT_PENALTIES.map((rule) => rule.token));
|
|
126
|
+
|
|
127
|
+
const REQUESTED_VARIANT_ALIASES = Object.freeze({
|
|
128
|
+
off: ['disabled', 'disable', 'muted', 'mute', 'off', 'broken'],
|
|
129
|
+
brand: ['brand', 'logo'],
|
|
130
|
+
open: ['open', 'unlock', 'unlocked'],
|
|
131
|
+
unlock: ['open', 'unlock', 'unlocked'],
|
|
132
|
+
ban: ['ban', 'banned', 'block', 'blocked'],
|
|
133
|
+
blocked: ['ban', 'banned', 'block', 'blocked'],
|
|
134
|
+
add: ['add', 'create', 'plus'],
|
|
135
|
+
plus: ['add', 'create', 'plus'],
|
|
136
|
+
edit: ['edit', 'editing', 'modify', 'pencil'],
|
|
137
|
+
remove: ['remove', 'removed', 'delete', 'minus'],
|
|
138
|
+
delete: ['delete', 'remove', 'trash'],
|
|
139
|
+
minus: ['minus', 'remove', 'removed', 'delete'],
|
|
140
|
+
cancel: ['cancel', 'canceled', 'cancelled', 'disabled', 'remove'],
|
|
141
|
+
x: ['x', 'close', 'remove', 'delete', 'blocked', 'broken', 'off'],
|
|
142
|
+
exclamation: ['alert', 'warning', 'exclamation'],
|
|
143
|
+
discount: ['discount', 'coupon', 'coupons', 'promo', 'promotion', 'deal'],
|
|
144
|
+
heart: ['heart', 'favorite', 'favourite', 'liked', 'wishlist'],
|
|
145
|
+
ai: ['ai', 'smart', 'assistant', 'automation'],
|
|
146
|
+
break: ['break', 'broken'],
|
|
147
|
+
broken: ['break', 'broken'],
|
|
148
|
+
locked: ['lock', 'locked', 'secure', 'security'],
|
|
149
|
+
ruble: ['ruble', 'rouble', 'rub'],
|
|
150
|
+
franc: ['franc', 'chf'],
|
|
151
|
+
lira: ['lira'],
|
|
152
|
+
bitcoin: ['bitcoin', 'btc'],
|
|
153
|
+
dollar: ['dollar', 'usd'],
|
|
154
|
+
yuan: ['yuan', 'cny'],
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const DIRECT_LOCALIZED_INTENT_RULES = Object.freeze([
|
|
158
|
+
{
|
|
159
|
+
pattern: /\u901a\u77e5|\u304a\u77e5\u3089\u305b|\uc54c\ub9bc|notificaciones?|benachrichtigungen?|notifica(?:\u00e7|c)[a\u00e3]o|notifica(?:\u00e7|c)[o\u00f5]es?|notificacoes?/iu,
|
|
160
|
+
terms: ['notification', 'notifications'],
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
pattern: /\u5173\u95ed|\u95dc\u9589|\u30aa\u30d5|\uaebc\uc9d0|\ub044\uae30|desactivad[ao]s?|apagad[ao]s?|aus\b|deaktiviert|disabled|muted|mute|off/iu,
|
|
164
|
+
terms: ['off', 'disabled'],
|
|
165
|
+
},
|
|
166
|
+
]);
|
|
144
167
|
|
|
145
|
-
const COMMON_SLOT_PREFERENCE_RULES = Object.freeze([
|
|
146
|
-
{
|
|
147
|
-
slotPatterns: [/\busers\b/i, /team/i, /members?/i],
|
|
148
|
-
queryVariants: ['users', 'team', 'user group', 'people'],
|
|
149
|
-
iconPreferences: [
|
|
150
|
-
{ pattern: /^users(?:_|-|$)|(?:_|-)users(?:_|-|$)|users-group|user-group|user_circle|user-circle/i, bonus: 66 },
|
|
151
|
-
{ pattern: /^user(?:_|-|$)|(?:_|-)user(?:_|-|$)/i, bonus: 18 },
|
|
152
|
-
],
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
slotPatterns: [
|
|
156
|
-
/profile/i,
|
|
157
|
-
/account/i,
|
|
158
|
-
/\buser\b/i,
|
|
159
|
-
/\busers\b/i,
|
|
160
|
-
/avatar/i,
|
|
161
|
-
/\u8d26\u6237|\u5e10\u6237|\u5e33\u6236|\u500b\u4eba\u8cc7\u6599|\u4e2a\u4eba\u8d44\u6599|\u7528\u6237|\u4f7f\u7528\u8005/u,
|
|
162
|
-
/\u30a2\u30ab\u30a6\u30f3\u30c8|\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb|\u30e6\u30fc\u30b6\u30fc/u,
|
|
163
|
-
/\uacc4\uc815|\ud504\ub85c\ud544|\uc0ac\uc6a9\uc790/u,
|
|
164
|
-
/cuenta|perfil|usuario/i,
|
|
165
|
-
/konto|profil|benutzer/i,
|
|
166
|
-
/conta|perfil|usu[aá]rio|utilizador/i,
|
|
167
|
-
/\u0627\u0644\u062d\u0633\u0627\u0628|\u0645\u0644\u0641\s+\u0634\u062e\u0635\u064a|\u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645/u,
|
|
168
|
-
/\u0916\u093e\u0924\u093e|\u092a\u094d\u0930\u094b\u092b\u093c\u093e\u0907\u0932|\u092a\u094d\u0930\u094b\u092b\u093e\u0907\u0932|\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e/u,
|
|
169
|
-
/t[aà]i kho[aả]n|tai khoan|h[oồ] s[oơ]|ho so|ng[uư][oờ]i d[uù]ng|nguoi dung/i,
|
|
170
|
-
/\u0e1a\u0e31\u0e0d\u0e0a\u0e35|\u0e42\u0e1b\u0e23\u0e44\u0e1f\u0e25\u0e4c|\u0e1c\u0e39\u0e49\u0e43\u0e0a\u0e49/u,
|
|
171
|
-
],
|
|
172
|
-
queryVariants: ['user profile', 'account user', 'avatar person', 'user'],
|
|
173
|
-
iconPreferences: [
|
|
174
|
-
{ pattern: /^user(?:_|-|$)|(?:_|-)user(?:_|-|$)|users|profile|avatar|circle-user|user-circle/i, bonus: 42 },
|
|
175
|
-
{ pattern: /person|contact/i, bonus: 12 },
|
|
176
|
-
],
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
slotPatterns: [
|
|
180
|
-
/\bhome\b/i,
|
|
181
|
-
/\bmain\b/i,
|
|
182
|
-
/\u9996\u9875|\u9996\u9801|\u4e3b\u9875|\u4e3b\u9801/u,
|
|
183
|
-
/\u30db\u30fc\u30e0|\u30e1\u30a4\u30f3/u,
|
|
184
|
-
/\ud648|\uba54\uc778/u,
|
|
185
|
-
/inicio|principal/i,
|
|
186
|
-
/startseite|hauptseite/i,
|
|
187
|
-
/\u0627\u0644\u0631\u0626\u064a\u0633\u064a\u0629|\u0627\u0644\u0635\u0641\u062d\u0629\s+\u0627\u0644\u0631\u0626\u064a\u0633\u064a\u0629/u,
|
|
188
|
-
/\u0e2b\u0e19\u0e49\u0e32\u0e2b\u0e25\u0e31\u0e01/u,
|
|
189
|
-
],
|
|
190
|
-
queryVariants: ['home', 'house'],
|
|
191
|
-
iconPreferences: [
|
|
192
|
-
{ pattern: /^home(?:_|-|$)|(?:_|-)home(?:_|-|$)|house/i, bonus: 40 },
|
|
193
|
-
],
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
slotPatterns: [
|
|
197
|
-
/alerts?/i,
|
|
198
|
-
/notifications?/i,
|
|
199
|
-
/bell/i,
|
|
200
|
-
/\u901a\u77e5|\u63d0\u9192/u,
|
|
201
|
-
/\u30a2\u30e9\u30fc\u30c8|\u304a\u77e5\u3089\u305b|\u901a\u77e5/u,
|
|
202
|
-
/\uc54c\ub9bc/u,
|
|
203
|
-
/notificaci[oó]n|notificaciones|alerta/i,
|
|
204
|
-
/benachrichtigung|benachrichtigungen/i,
|
|
205
|
-
/notifica(?:ç|c)[aã]o|notifica(?:ç|c)[oõ]es|notificacoes|alerta/i,
|
|
206
|
-
/\u0627\u0644\u0625\u0634\u0639\u0627\u0631|\u0627\u0644\u0625\u0634\u0639\u0627\u0631\u0627\u062a/u,
|
|
207
|
-
/\u0938\u0942\u091a\u0928\u093e|\u0938\u0942\u091a\u0928\u093e\u090f\u0901|\u0905\u0927\u093f\u0938\u0942\u091a\u0928\u093e/u,
|
|
208
|
-
/th[oô]ng b[aá]o|thong bao|c[aả]nh b[aá]o|canh bao/i,
|
|
209
|
-
/\u0e41\u0e08\u0e49\u0e07\u0e40\u0e15\u0e37\u0e2d\u0e19|\u0e01\u0e32\u0e23\u0e41\u0e08\u0e49\u0e07\u0e40\u0e15\u0e37\u0e2d\u0e19/u,
|
|
210
|
-
],
|
|
211
|
-
queryVariants: ['notification', 'bell', 'alert', 'alarm'],
|
|
212
|
-
iconPreferences: [
|
|
213
|
-
{ pattern: /notification|bell/i, bonus: 46 },
|
|
214
|
-
{ pattern: /alarm|alert/i, bonus: 18 },
|
|
215
|
-
],
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
priority: 90,
|
|
219
|
-
slotPatterns: [/notifications?\s+off/i, /disabled notifications?/i, /muted notifications?/i, /notification\s+off/i],
|
|
220
|
-
queryVariants: ['bell slash', 'bell off', 'notification off', 'muted bell'],
|
|
221
|
-
iconPreferences: [
|
|
222
|
-
{ pattern: /^bell[_-]?(off|slash)$|^bell[_-]?simple[_-]?slash$|notification[_-]?off|notifications?[_-]?off/i, bonus: 180 },
|
|
223
|
-
{ pattern: /bell|notification/i, bonus: 22 },
|
|
224
|
-
],
|
|
225
|
-
},
|
|
226
|
-
{
|
|
227
|
-
slotPatterns: [
|
|
228
|
-
/privacy/i,
|
|
229
|
-
/security/i,
|
|
230
|
-
/private/i,
|
|
231
|
-
/safe/i,
|
|
232
|
-
/protection/i,
|
|
233
|
-
/\u9690\u79c1|\u96b1\u79c1|\u5b89\u5168/u,
|
|
234
|
-
/\u30d7\u30e9\u30a4\u30d0\u30b7\u30fc|\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3|\u5b89\u5168/u,
|
|
235
|
-
/\uac1c\uc778\uc815\ubcf4|\uac1c\uc778\s+\uc815\ubcf4|\ubcf4\uc548|\uc548\uc804/u,
|
|
236
|
-
/privacidad|seguridad/i,
|
|
237
|
-
/datenschutz|sicherheit/i,
|
|
238
|
-
/privacidade|seguran[cç]a|seguranca/i,
|
|
239
|
-
/\u0627\u0644\u062e\u0635\u0648\u0635\u064a\u0629|\u0627\u0644\u0623\u0645\u0627\u0646|\u0627\u0644\u0627\u0645\u0627\u0646|\u0627\u0644\u0623\u0645\u0646|\u0627\u0644\u0627\u0645\u0646/u,
|
|
240
|
-
/\u0917\u094b\u092a\u0928\u0940\u092f\u0924\u093e|\u0938\u0941\u0930\u0915\u094d\u0937\u093e/u,
|
|
241
|
-
/quy[eề]n ri[eê]ng t[uư]|quyen rieng tu|b[aả]o m[aậ]t|bao mat|an to[aà]n|an toan/i,
|
|
242
|
-
/\u0e04\u0e27\u0e32\u0e21\u0e40\u0e1b\u0e47\u0e19\u0e2a\u0e48\u0e27\u0e19\u0e15\u0e31\u0e27|\u0e04\u0e27\u0e32\u0e21\u0e1b\u0e25\u0e2d\u0e14\u0e20\u0e31\u0e22/u,
|
|
243
|
-
],
|
|
244
|
-
queryVariants: ['shield lock', 'lock', 'shield', 'privacy security', 'security'],
|
|
245
|
-
iconPreferences: [
|
|
246
|
-
{ pattern: /^shield$|^shield[_-]?check$|shield-check|shield_check/i, bonus: 82 },
|
|
247
|
-
{ pattern: /shield.*lock|lock.*shield|shield/i, bonus: 58 },
|
|
248
|
-
{ pattern: /^lock$|^lock[_-]?keyhole$|(?:_|-)lock(?:_|-|$)|key|fingerprint/i, bonus: 34 },
|
|
249
|
-
{ pattern: /open|unlock|ban|minus|off|slash/i, bonus: -54 },
|
|
250
|
-
],
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
priority: 120,
|
|
254
|
-
slotPatterns: [/unlock/i, /open account/i, /unlocked account/i],
|
|
255
|
-
queryVariants: ['lock open', 'unlock', 'lock keyhole open'],
|
|
256
|
-
iconPreferences: [
|
|
257
|
-
{ pattern: /^lock[_-]?open$|^lock[_-]?keyhole[_-]?open$|^unlock(?:[_-]?keyhole)?$/i, bonus: 160 },
|
|
258
|
-
{ pattern: /lock.*open|open.*lock|unlock/i, bonus: 80 },
|
|
259
|
-
{ pattern: /^user(?:_|-|$)|(?:_|-)user(?:_|-|$)|file-user/i, bonus: -70 },
|
|
260
|
-
],
|
|
261
|
-
},
|
|
262
|
-
{
|
|
263
|
-
priority: 120,
|
|
264
|
-
slotPatterns: [/blocked user/i, /banned user/i, /user blocked/i, /user banned/i],
|
|
265
|
-
queryVariants: ['user x', 'user minus', 'ban user', 'blocked user'],
|
|
266
|
-
iconPreferences: [
|
|
267
|
-
{ pattern: /^user[_-]?x$|^user[_-]?minus$|user-round-x|user-round-minus|shield-ban|ban/i, bonus: 150 },
|
|
268
|
-
{ pattern: /^user(?:_|-|$)|(?:_|-)user(?:_|-|$)/i, bonus: 24 },
|
|
269
|
-
{ pattern: /^file-user$|^user-2$/i, bonus: -80 },
|
|
270
|
-
],
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
slotPatterns: [
|
|
274
|
-
/appearance/i,
|
|
275
|
-
/theme/i,
|
|
276
|
-
/color/i,
|
|
277
|
-
/palette/i,
|
|
278
|
-
/dark mode/i,
|
|
279
|
-
/light mode/i,
|
|
280
|
-
/\u5916\u89c2|\u5916\u89c0|\u4e3b\u9898|\u4e3b\u984c|\u989c\u8272|\u984f\u8272/u,
|
|
281
|
-
/\u5916\u89b3|\u30c6\u30fc\u30de|\u8868\u793a|\u914d\u8272/u,
|
|
282
|
-
/\uc678\uad00|\ud14c\ub9c8|\uc0c9\uc0c1|\ud654\uba74/u,
|
|
283
|
-
/apariencia|tema|colou?r|modo/i,
|
|
284
|
-
/erscheinungsbild|design|darstellung|thema/i,
|
|
285
|
-
/apar[eê]ncia|tema|cor/i,
|
|
286
|
-
/\u0627\u0644\u0645\u0638\u0647\u0631|\u0627\u0644\u0633\u0645\u0629|\u0627\u0644\u0648\u0636\u0639|\u0627\u0644\u0623\u0644\u0648\u0627\u0646/u,
|
|
287
|
-
/\u0930\u0942\u092a|\u0925\u0940\u092e|\u0926\u093f\u0916\u093e\u0935\u091f|\u0930\u0902\u0917/u,
|
|
288
|
-
/giao di[eệ]n|giao dien|ch[uủ] \u0111[eề]|chu de|m[aà]u|mau/i,
|
|
289
|
-
/\u0e23\u0e39\u0e1b\u0e25\u0e31\u0e01\u0e29\u0e13\u0e4c|\u0e18\u0e35\u0e21|\u0e2a\u0e35|\u0e2b\u0e19\u0e49\u0e32\u0e15\u0e32/u,
|
|
290
|
-
],
|
|
291
|
-
queryVariants: ['palette', 'moon', 'theme', 'sun moon', 'appearance'],
|
|
292
|
-
iconPreferences: [
|
|
293
|
-
{ pattern: /^palette$|paint|brush|color|swatch/i, bonus: 54 },
|
|
294
|
-
{ pattern: /^moon$|sun-moon|sun|theme/i, bonus: 28 },
|
|
295
|
-
],
|
|
296
|
-
},
|
|
297
|
-
{
|
|
298
|
-
slotPatterns: [
|
|
299
|
-
/language/i,
|
|
300
|
-
/locale/i,
|
|
301
|
-
/translate/i,
|
|
302
|
-
/translation/i,
|
|
303
|
-
/\u8bed\u8a00/u,
|
|
304
|
-
/\u8a9e\u8a00/u,
|
|
305
|
-
/\u8a00\u8a9e/u,
|
|
306
|
-
/\uc5b8\uc5b4/u,
|
|
307
|
-
/idioma/i,
|
|
308
|
-
/sprache/i,
|
|
309
|
-
/l[ií]ngua/i,
|
|
310
|
-
/langue/i,
|
|
311
|
-
/\u0627\u0644\u0644\u063a\u0629|\u0644\u063a\u0629/u,
|
|
312
|
-
/\u092d\u093e\u0937\u093e/u,
|
|
313
|
-
/ng[oô]n ng[uữ]|ngon ngu/i,
|
|
314
|
-
/\u0e20\u0e32\u0e29\u0e32/u,
|
|
315
|
-
],
|
|
316
|
-
queryVariants: ['globe', 'languages', 'translate', 'language'],
|
|
317
|
-
iconPreferences: [
|
|
318
|
-
{ pattern: /^globe$|^languages?$|^translate$|(?:_|-)(globe|languages?|translate)(?:_|-|$)/i, bonus: 70 },
|
|
319
|
-
{ pattern: /globe|language|translate/i, bonus: 28 },
|
|
320
|
-
],
|
|
321
|
-
},
|
|
322
|
-
{
|
|
323
|
-
slotPatterns: [
|
|
324
|
-
/language/i,
|
|
325
|
-
/locale/i,
|
|
326
|
-
/translate/i,
|
|
327
|
-
/translation/i,
|
|
328
|
-
/语言/u,
|
|
329
|
-
/語言/u,
|
|
330
|
-
/言語/u,
|
|
331
|
-
/언어/u,
|
|
332
|
-
/idioma/i,
|
|
333
|
-
/sprache/i,
|
|
334
|
-
/língua/i,
|
|
335
|
-
/langue/i,
|
|
336
|
-
/اللغة/u,
|
|
337
|
-
/भाषा/u,
|
|
338
|
-
/ngôn ngữ/i,
|
|
339
|
-
/ภาษา/u,
|
|
340
|
-
],
|
|
341
|
-
queryVariants: ['globe', 'languages', 'translate', 'language'],
|
|
342
|
-
iconPreferences: [
|
|
343
|
-
{ pattern: /^globe$|^languages?$|^translate$|(?:_|-)(globe|languages?|translate)(?:_|-|$)/i, bonus: 70 },
|
|
344
|
-
{ pattern: /globe|language|translate/i, bonus: 28 },
|
|
345
|
-
],
|
|
346
|
-
},
|
|
347
|
-
{
|
|
348
|
-
slotPatterns: [/create/i, /\badd\b/i, /\bplus\b/i, /compose/i, /new item/i],
|
|
349
|
-
queryVariants: ['add', 'plus', 'create new', 'compose'],
|
|
350
|
-
iconPreferences: [
|
|
351
|
-
{ pattern: /^(add|plus)(?:_|-|$)/i, bonus: 48 },
|
|
352
|
-
{ pattern: /(?:_|-)(add|plus)(?:_|-|$)/i, bonus: 18 },
|
|
353
|
-
{ pattern: /compose|edit|pencil/i, bonus: 8 },
|
|
354
|
-
],
|
|
355
|
-
},
|
|
356
|
-
{
|
|
357
|
-
slotPatterns: [/archive/i],
|
|
358
|
-
queryVariants: ['archive', 'archive box', 'box archive'],
|
|
359
|
-
iconPreferences: [
|
|
360
|
-
{ pattern: /^archive(?:_|-|$)|(?:_|-)archive(?:_|-|$)/i, bonus: 40 },
|
|
361
|
-
{ pattern: /box|tray/i, bonus: 8 },
|
|
362
|
-
],
|
|
363
|
-
},
|
|
364
|
-
{
|
|
365
|
-
slotPatterns: [/alerts?/i, /notifications?/i, /bell/i, /通知/u, /알림/u, /通知/u],
|
|
366
|
-
queryVariants: ['notification', 'bell', 'alert', 'alarm'],
|
|
168
|
+
const COMMON_SLOT_PREFERENCE_RULES = Object.freeze([
|
|
169
|
+
{
|
|
170
|
+
slotPatterns: [/\busers\b/i, /team/i, /members?/i],
|
|
171
|
+
queryVariants: ['users', 'team', 'user group', 'people'],
|
|
172
|
+
iconPreferences: [
|
|
173
|
+
{ pattern: /^users(?:_|-|$)|(?:_|-)users(?:_|-|$)|users-group|user-group|user_circle|user-circle/i, bonus: 66 },
|
|
174
|
+
{ pattern: /^user(?:_|-|$)|(?:_|-)user(?:_|-|$)/i, bonus: 18 },
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
slotPatterns: [
|
|
179
|
+
/profile/i,
|
|
180
|
+
/account/i,
|
|
181
|
+
/\buser\b/i,
|
|
182
|
+
/\busers\b/i,
|
|
183
|
+
/avatar/i,
|
|
184
|
+
/\u8d26\u6237|\u5e10\u6237|\u5e33\u6236|\u500b\u4eba\u8cc7\u6599|\u4e2a\u4eba\u8d44\u6599|\u7528\u6237|\u4f7f\u7528\u8005/u,
|
|
185
|
+
/\u30a2\u30ab\u30a6\u30f3\u30c8|\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb|\u30e6\u30fc\u30b6\u30fc/u,
|
|
186
|
+
/\uacc4\uc815|\ud504\ub85c\ud544|\uc0ac\uc6a9\uc790/u,
|
|
187
|
+
/cuenta|perfil|usuario/i,
|
|
188
|
+
/konto|profil|benutzer/i,
|
|
189
|
+
/conta|perfil|usu[aá]rio|utilizador/i,
|
|
190
|
+
/\u0627\u0644\u062d\u0633\u0627\u0628|\u0645\u0644\u0641\s+\u0634\u062e\u0635\u064a|\u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645/u,
|
|
191
|
+
/\u0916\u093e\u0924\u093e|\u092a\u094d\u0930\u094b\u092b\u093c\u093e\u0907\u0932|\u092a\u094d\u0930\u094b\u092b\u093e\u0907\u0932|\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e/u,
|
|
192
|
+
/t[aà]i kho[aả]n|tai khoan|h[oồ] s[oơ]|ho so|ng[uư][oờ]i d[uù]ng|nguoi dung/i,
|
|
193
|
+
/\u0e1a\u0e31\u0e0d\u0e0a\u0e35|\u0e42\u0e1b\u0e23\u0e44\u0e1f\u0e25\u0e4c|\u0e1c\u0e39\u0e49\u0e43\u0e0a\u0e49/u,
|
|
194
|
+
],
|
|
195
|
+
queryVariants: ['user profile', 'account user', 'avatar person', 'user'],
|
|
196
|
+
iconPreferences: [
|
|
197
|
+
{ pattern: /^user(?:_|-|$)|(?:_|-)user(?:_|-|$)|users|profile|avatar|circle-user|user-circle/i, bonus: 42 },
|
|
198
|
+
{ pattern: /person|contact/i, bonus: 12 },
|
|
199
|
+
],
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
slotPatterns: [
|
|
203
|
+
/\bhome\b/i,
|
|
204
|
+
/\bmain\b/i,
|
|
205
|
+
/\u9996\u9875|\u9996\u9801|\u4e3b\u9875|\u4e3b\u9801/u,
|
|
206
|
+
/\u30db\u30fc\u30e0|\u30e1\u30a4\u30f3/u,
|
|
207
|
+
/\ud648|\uba54\uc778/u,
|
|
208
|
+
/inicio|principal/i,
|
|
209
|
+
/startseite|hauptseite/i,
|
|
210
|
+
/\u0627\u0644\u0631\u0626\u064a\u0633\u064a\u0629|\u0627\u0644\u0635\u0641\u062d\u0629\s+\u0627\u0644\u0631\u0626\u064a\u0633\u064a\u0629/u,
|
|
211
|
+
/\u0e2b\u0e19\u0e49\u0e32\u0e2b\u0e25\u0e31\u0e01/u,
|
|
212
|
+
],
|
|
213
|
+
queryVariants: ['home', 'house'],
|
|
214
|
+
iconPreferences: [
|
|
215
|
+
{ pattern: /^home(?:_|-|$)|(?:_|-)home(?:_|-|$)|house/i, bonus: 40 },
|
|
216
|
+
],
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
slotPatterns: [
|
|
220
|
+
/alerts?/i,
|
|
221
|
+
/notifications?/i,
|
|
222
|
+
/bell/i,
|
|
223
|
+
/\u901a\u77e5|\u63d0\u9192/u,
|
|
224
|
+
/\u30a2\u30e9\u30fc\u30c8|\u304a\u77e5\u3089\u305b|\u901a\u77e5/u,
|
|
225
|
+
/\uc54c\ub9bc/u,
|
|
226
|
+
/notificaci[oó]n|notificaciones|alerta/i,
|
|
227
|
+
/benachrichtigung|benachrichtigungen/i,
|
|
228
|
+
/notifica(?:ç|c)[aã]o|notifica(?:ç|c)[oõ]es|notificacoes|alerta/i,
|
|
229
|
+
/\u0627\u0644\u0625\u0634\u0639\u0627\u0631|\u0627\u0644\u0625\u0634\u0639\u0627\u0631\u0627\u062a/u,
|
|
230
|
+
/\u0938\u0942\u091a\u0928\u093e|\u0938\u0942\u091a\u0928\u093e\u090f\u0901|\u0905\u0927\u093f\u0938\u0942\u091a\u0928\u093e/u,
|
|
231
|
+
/th[oô]ng b[aá]o|thong bao|c[aả]nh b[aá]o|canh bao/i,
|
|
232
|
+
/\u0e41\u0e08\u0e49\u0e07\u0e40\u0e15\u0e37\u0e2d\u0e19|\u0e01\u0e32\u0e23\u0e41\u0e08\u0e49\u0e07\u0e40\u0e15\u0e37\u0e2d\u0e19/u,
|
|
233
|
+
],
|
|
234
|
+
queryVariants: ['notification', 'bell', 'alert', 'alarm'],
|
|
235
|
+
iconPreferences: [
|
|
236
|
+
{ pattern: /notification|bell/i, bonus: 46 },
|
|
237
|
+
{ pattern: /alarm|alert/i, bonus: 18 },
|
|
238
|
+
],
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
priority: 90,
|
|
242
|
+
slotPatterns: [/notifications?\s+off/i, /disabled notifications?/i, /muted notifications?/i, /notification\s+off/i],
|
|
243
|
+
queryVariants: ['bell slash', 'bell off', 'notification off', 'muted bell'],
|
|
244
|
+
iconPreferences: [
|
|
245
|
+
{ pattern: /^bell[_-]?(off|slash)$|^bell[_-]?simple[_-]?slash$|notification[_-]?off|notifications?[_-]?off/i, bonus: 180 },
|
|
246
|
+
{ pattern: /bell|notification/i, bonus: 22 },
|
|
247
|
+
],
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
slotPatterns: [
|
|
251
|
+
/privacy/i,
|
|
252
|
+
/security/i,
|
|
253
|
+
/private/i,
|
|
254
|
+
/safe/i,
|
|
255
|
+
/protection/i,
|
|
256
|
+
/\u9690\u79c1|\u96b1\u79c1|\u5b89\u5168/u,
|
|
257
|
+
/\u30d7\u30e9\u30a4\u30d0\u30b7\u30fc|\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3|\u5b89\u5168/u,
|
|
258
|
+
/\uac1c\uc778\uc815\ubcf4|\uac1c\uc778\s+\uc815\ubcf4|\ubcf4\uc548|\uc548\uc804/u,
|
|
259
|
+
/privacidad|seguridad/i,
|
|
260
|
+
/datenschutz|sicherheit/i,
|
|
261
|
+
/privacidade|seguran[cç]a|seguranca/i,
|
|
262
|
+
/\u0627\u0644\u062e\u0635\u0648\u0635\u064a\u0629|\u0627\u0644\u0623\u0645\u0627\u0646|\u0627\u0644\u0627\u0645\u0627\u0646|\u0627\u0644\u0623\u0645\u0646|\u0627\u0644\u0627\u0645\u0646/u,
|
|
263
|
+
/\u0917\u094b\u092a\u0928\u0940\u092f\u0924\u093e|\u0938\u0941\u0930\u0915\u094d\u0937\u093e/u,
|
|
264
|
+
/quy[eề]n ri[eê]ng t[uư]|quyen rieng tu|b[aả]o m[aậ]t|bao mat|an to[aà]n|an toan/i,
|
|
265
|
+
/\u0e04\u0e27\u0e32\u0e21\u0e40\u0e1b\u0e47\u0e19\u0e2a\u0e48\u0e27\u0e19\u0e15\u0e31\u0e27|\u0e04\u0e27\u0e32\u0e21\u0e1b\u0e25\u0e2d\u0e14\u0e20\u0e31\u0e22/u,
|
|
266
|
+
],
|
|
267
|
+
queryVariants: ['shield lock', 'lock', 'shield', 'privacy security', 'security'],
|
|
268
|
+
iconPreferences: [
|
|
269
|
+
{ pattern: /^shield$|^shield[_-]?check$|shield-check|shield_check/i, bonus: 82 },
|
|
270
|
+
{ pattern: /shield.*lock|lock.*shield|shield/i, bonus: 58 },
|
|
271
|
+
{ pattern: /^lock$|^lock[_-]?keyhole$|(?:_|-)lock(?:_|-|$)|key|fingerprint/i, bonus: 34 },
|
|
272
|
+
{ pattern: /open|unlock|ban|minus|off|slash/i, bonus: -54 },
|
|
273
|
+
],
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
priority: 120,
|
|
277
|
+
slotPatterns: [/unlock/i, /open account/i, /unlocked account/i],
|
|
278
|
+
queryVariants: ['lock open', 'unlock', 'lock keyhole open'],
|
|
279
|
+
iconPreferences: [
|
|
280
|
+
{ pattern: /^lock[_-]?open$|^lock[_-]?keyhole[_-]?open$|^unlock(?:[_-]?keyhole)?$/i, bonus: 160 },
|
|
281
|
+
{ pattern: /lock.*open|open.*lock|unlock/i, bonus: 80 },
|
|
282
|
+
{ pattern: /^user(?:_|-|$)|(?:_|-)user(?:_|-|$)|file-user/i, bonus: -70 },
|
|
283
|
+
],
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
priority: 120,
|
|
287
|
+
slotPatterns: [/blocked user/i, /banned user/i, /user blocked/i, /user banned/i],
|
|
288
|
+
queryVariants: ['user x', 'user minus', 'ban user', 'blocked user'],
|
|
289
|
+
iconPreferences: [
|
|
290
|
+
{ pattern: /^user[_-]?x$|^user[_-]?minus$|user-round-x|user-round-minus|shield-ban|ban/i, bonus: 150 },
|
|
291
|
+
{ pattern: /^user(?:_|-|$)|(?:_|-)user(?:_|-|$)/i, bonus: 24 },
|
|
292
|
+
{ pattern: /^file-user$|^user-2$/i, bonus: -80 },
|
|
293
|
+
],
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
slotPatterns: [
|
|
297
|
+
/appearance/i,
|
|
298
|
+
/theme/i,
|
|
299
|
+
/color/i,
|
|
300
|
+
/palette/i,
|
|
301
|
+
/dark mode/i,
|
|
302
|
+
/light mode/i,
|
|
303
|
+
/\u5916\u89c2|\u5916\u89c0|\u4e3b\u9898|\u4e3b\u984c|\u989c\u8272|\u984f\u8272/u,
|
|
304
|
+
/\u5916\u89b3|\u30c6\u30fc\u30de|\u8868\u793a|\u914d\u8272/u,
|
|
305
|
+
/\uc678\uad00|\ud14c\ub9c8|\uc0c9\uc0c1|\ud654\uba74/u,
|
|
306
|
+
/apariencia|tema|colou?r|modo/i,
|
|
307
|
+
/erscheinungsbild|design|darstellung|thema/i,
|
|
308
|
+
/apar[eê]ncia|tema|cor/i,
|
|
309
|
+
/\u0627\u0644\u0645\u0638\u0647\u0631|\u0627\u0644\u0633\u0645\u0629|\u0627\u0644\u0648\u0636\u0639|\u0627\u0644\u0623\u0644\u0648\u0627\u0646/u,
|
|
310
|
+
/\u0930\u0942\u092a|\u0925\u0940\u092e|\u0926\u093f\u0916\u093e\u0935\u091f|\u0930\u0902\u0917/u,
|
|
311
|
+
/giao di[eệ]n|giao dien|ch[uủ] \u0111[eề]|chu de|m[aà]u|mau/i,
|
|
312
|
+
/\u0e23\u0e39\u0e1b\u0e25\u0e31\u0e01\u0e29\u0e13\u0e4c|\u0e18\u0e35\u0e21|\u0e2a\u0e35|\u0e2b\u0e19\u0e49\u0e32\u0e15\u0e32/u,
|
|
313
|
+
],
|
|
314
|
+
queryVariants: ['palette', 'moon', 'theme', 'sun moon', 'appearance'],
|
|
315
|
+
iconPreferences: [
|
|
316
|
+
{ pattern: /^palette$|paint|brush|color|swatch/i, bonus: 54 },
|
|
317
|
+
{ pattern: /^moon$|sun-moon|sun|theme/i, bonus: 28 },
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
slotPatterns: [
|
|
322
|
+
/language/i,
|
|
323
|
+
/locale/i,
|
|
324
|
+
/translate/i,
|
|
325
|
+
/translation/i,
|
|
326
|
+
/\u8bed\u8a00/u,
|
|
327
|
+
/\u8a9e\u8a00/u,
|
|
328
|
+
/\u8a00\u8a9e/u,
|
|
329
|
+
/\uc5b8\uc5b4/u,
|
|
330
|
+
/idioma/i,
|
|
331
|
+
/sprache/i,
|
|
332
|
+
/l[ií]ngua/i,
|
|
333
|
+
/langue/i,
|
|
334
|
+
/\u0627\u0644\u0644\u063a\u0629|\u0644\u063a\u0629/u,
|
|
335
|
+
/\u092d\u093e\u0937\u093e/u,
|
|
336
|
+
/ng[oô]n ng[uữ]|ngon ngu/i,
|
|
337
|
+
/\u0e20\u0e32\u0e29\u0e32/u,
|
|
338
|
+
],
|
|
339
|
+
queryVariants: ['globe', 'languages', 'translate', 'language'],
|
|
340
|
+
iconPreferences: [
|
|
341
|
+
{ pattern: /^globe$|^languages?$|^translate$|(?:_|-)(globe|languages?|translate)(?:_|-|$)/i, bonus: 70 },
|
|
342
|
+
{ pattern: /globe|language|translate/i, bonus: 28 },
|
|
343
|
+
],
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
slotPatterns: [
|
|
347
|
+
/language/i,
|
|
348
|
+
/locale/i,
|
|
349
|
+
/translate/i,
|
|
350
|
+
/translation/i,
|
|
351
|
+
/语言/u,
|
|
352
|
+
/語言/u,
|
|
353
|
+
/言語/u,
|
|
354
|
+
/언어/u,
|
|
355
|
+
/idioma/i,
|
|
356
|
+
/sprache/i,
|
|
357
|
+
/língua/i,
|
|
358
|
+
/langue/i,
|
|
359
|
+
/اللغة/u,
|
|
360
|
+
/भाषा/u,
|
|
361
|
+
/ngôn ngữ/i,
|
|
362
|
+
/ภาษา/u,
|
|
363
|
+
],
|
|
364
|
+
queryVariants: ['globe', 'languages', 'translate', 'language'],
|
|
365
|
+
iconPreferences: [
|
|
366
|
+
{ pattern: /^globe$|^languages?$|^translate$|(?:_|-)(globe|languages?|translate)(?:_|-|$)/i, bonus: 70 },
|
|
367
|
+
{ pattern: /globe|language|translate/i, bonus: 28 },
|
|
368
|
+
],
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
slotPatterns: [/create/i, /\badd\b/i, /\bplus\b/i, /compose/i, /new item/i],
|
|
372
|
+
queryVariants: ['add', 'plus', 'create new', 'compose'],
|
|
373
|
+
iconPreferences: [
|
|
374
|
+
{ pattern: /^(add|plus)(?:_|-|$)/i, bonus: 48 },
|
|
375
|
+
{ pattern: /(?:_|-)(add|plus)(?:_|-|$)/i, bonus: 18 },
|
|
376
|
+
{ pattern: /compose|edit|pencil/i, bonus: 8 },
|
|
377
|
+
],
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
slotPatterns: [/archive/i],
|
|
381
|
+
queryVariants: ['archive', 'archive box', 'box archive'],
|
|
382
|
+
iconPreferences: [
|
|
383
|
+
{ pattern: /^archive(?:_|-|$)|(?:_|-)archive(?:_|-|$)/i, bonus: 40 },
|
|
384
|
+
{ pattern: /box|tray/i, bonus: 8 },
|
|
385
|
+
],
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
slotPatterns: [/alerts?/i, /notifications?/i, /bell/i, /通知/u, /알림/u, /通知/u],
|
|
389
|
+
queryVariants: ['notification', 'bell', 'alert', 'alarm'],
|
|
367
390
|
iconPreferences: [
|
|
368
391
|
{ pattern: /notification|bell/i, bonus: 42 },
|
|
369
392
|
{ pattern: /alarm|alert/i, bonus: 16 },
|
|
@@ -377,33 +400,33 @@ const COMMON_SLOT_PREFERENCE_RULES = Object.freeze([
|
|
|
377
400
|
{ pattern: /person|contact/i, bonus: 10 },
|
|
378
401
|
],
|
|
379
402
|
},
|
|
380
|
-
{
|
|
381
|
-
slotPatterns: [/model/i, /\bai\b/i, /\bml\b/i, /machine learning/i],
|
|
382
|
-
queryVariants: ['brain circuit', 'brain cog', 'neural network', 'model'],
|
|
403
|
+
{
|
|
404
|
+
slotPatterns: [/model/i, /\bai\b/i, /\bml\b/i, /machine learning/i],
|
|
405
|
+
queryVariants: ['brain circuit', 'brain cog', 'neural network', 'model'],
|
|
383
406
|
iconPreferences: [
|
|
384
407
|
{ pattern: /brain-circuit|brain_circuit/i, bonus: 44 },
|
|
385
|
-
{ pattern: /brain|circuit|nodes/i, bonus: 24 },
|
|
386
|
-
],
|
|
387
|
-
},
|
|
388
|
-
{
|
|
389
|
-
priority: 120,
|
|
390
|
-
slotPatterns: [/\bai search\b/i, /smart search/i, /semantic search/i, /assistant search/i],
|
|
391
|
-
queryVariants: ['search ai', 'ai search', 'smart search'],
|
|
392
|
-
iconPreferences: [
|
|
393
|
-
{ pattern: /^search.*ai|ai.*search|search[_-]?[23]?[_-]?ai/i, bonus: 150 },
|
|
394
|
-
{ pattern: /^search(?:_|-|$)|(?:_|-)search(?:_|-|$)/i, bonus: 34 },
|
|
395
|
-
{ pattern: /brain|robot|spark/i, bonus: 24 },
|
|
396
|
-
],
|
|
397
|
-
},
|
|
398
|
-
{
|
|
399
|
-
priority: 90,
|
|
400
|
-
slotPatterns: [/automation/i, /workflow/i, /automate/i, /smart action/i],
|
|
401
|
-
queryVariants: ['automation', 'workflow', 'robot', 'refresh', 'sparkles'],
|
|
402
|
-
iconPreferences: [
|
|
403
|
-
{ pattern: /workflow|automation|robot|sparkles?|refresh|settings|adjustments/i, bonus: 90 },
|
|
404
|
-
{ pattern: /hand|finger|train/i, bonus: -90 },
|
|
405
|
-
],
|
|
406
|
-
},
|
|
408
|
+
{ pattern: /brain|circuit|nodes/i, bonus: 24 },
|
|
409
|
+
],
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
priority: 120,
|
|
413
|
+
slotPatterns: [/\bai search\b/i, /smart search/i, /semantic search/i, /assistant search/i],
|
|
414
|
+
queryVariants: ['search ai', 'ai search', 'smart search'],
|
|
415
|
+
iconPreferences: [
|
|
416
|
+
{ pattern: /^search.*ai|ai.*search|search[_-]?[23]?[_-]?ai/i, bonus: 150 },
|
|
417
|
+
{ pattern: /^search(?:_|-|$)|(?:_|-)search(?:_|-|$)/i, bonus: 34 },
|
|
418
|
+
{ pattern: /brain|robot|spark/i, bonus: 24 },
|
|
419
|
+
],
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
priority: 90,
|
|
423
|
+
slotPatterns: [/automation/i, /workflow/i, /automate/i, /smart action/i],
|
|
424
|
+
queryVariants: ['automation', 'workflow', 'robot', 'refresh', 'sparkles'],
|
|
425
|
+
iconPreferences: [
|
|
426
|
+
{ pattern: /workflow|automation|robot|sparkles?|refresh|settings|adjustments/i, bonus: 90 },
|
|
427
|
+
{ pattern: /hand|finger|train/i, bonus: -90 },
|
|
428
|
+
],
|
|
429
|
+
},
|
|
407
430
|
{
|
|
408
431
|
slotPatterns: [/prompt/i],
|
|
409
432
|
queryVariants: ['message text', 'text input', 'terminal', 'text cursor'],
|
|
@@ -444,430 +467,430 @@ const COMMON_SLOT_PREFERENCE_RULES = Object.freeze([
|
|
|
444
467
|
{ pattern: /chart|signal|radar/i, bonus: 16 },
|
|
445
468
|
],
|
|
446
469
|
},
|
|
447
|
-
{
|
|
448
|
-
slotPatterns: [/billing/i, /payment/i, /invoice/i, /subscription/i],
|
|
449
|
-
queryVariants: ['credit card', 'receipt', 'invoice', 'payment', 'wallet'],
|
|
450
|
-
iconPreferences: [
|
|
451
|
-
{ pattern: /credit-card|receipt|wallet|invoice/i, bonus: 44 },
|
|
452
|
-
{ pattern: /card|banknote|currency|dollar/i, bonus: 18 },
|
|
453
|
-
{ pattern: /ruble|franc|lira|bitcoin|yuan/i, bonus: -70 },
|
|
454
|
-
],
|
|
455
|
-
},
|
|
456
|
-
{
|
|
457
|
-
priority: 90,
|
|
458
|
-
slotPatterns: [/storefront/i, /\bstore\b/i, /\bshop\b/i],
|
|
459
|
-
queryVariants: ['store', 'shop', 'building store', 'shopping bag'],
|
|
460
|
-
iconPreferences: [
|
|
461
|
-
{ pattern: /^store$|^storefront$|building-store|shop[_-]?line|store[_-]?\d?[_-]?line|shopping-bag/i, bonus: 120 },
|
|
462
|
-
{ pattern: /brand-appstore|restore|cancel|\bx\b|off|discount|heart|exclamation|minus|plus|search|share|star|question|bolt|code|copy|dollar|down|up|pin|pause/i, bonus: -120 },
|
|
463
|
-
],
|
|
464
|
-
},
|
|
465
|
-
{
|
|
466
|
-
priority: 130,
|
|
467
|
-
slotPatterns: [/(store|shop|storefront)\s+(off|disabled|closed|cancelled|canceled)/i, /(off|disabled|closed|cancelled|canceled)\s+(store|shop|storefront)/i],
|
|
468
|
-
queryVariants: ['store off', 'shopping bag x', 'shopping cart off', 'store disabled'],
|
|
469
|
-
iconPreferences: [
|
|
470
|
-
{ pattern: /(store|shop|shopping|bag|cart).*(off|\bx\b|cancel|disabled)|(off|\bx\b|cancel|disabled).*(store|shop|shopping|bag|cart)/i, bonus: 220 },
|
|
471
|
-
{ pattern: /^building-store$|^store$|^shopping-bag$/i, bonus: -70 },
|
|
472
|
-
],
|
|
473
|
-
},
|
|
474
|
-
{
|
|
475
|
-
priority: 90,
|
|
476
|
-
slotPatterns: [/checkout/i],
|
|
477
|
-
queryVariants: ['shopping cart', 'credit card', 'payment', 'receipt checkout'],
|
|
478
|
-
iconPreferences: [
|
|
479
|
-
{ pattern: /^shopping[_-]?cart$|shopping-cart$|credit-card|card-pay|payment|receipt/i, bonus: 140 },
|
|
480
|
-
{ pattern: /fork|knife|git|branch|merge|forklift|grill|cancel|\bx\b|off|discount|heart|exclamation|minus|plus|search|share|star|question|bolt|code|copy|dollar|down|up|pin|pause/i, bonus: -140 },
|
|
481
|
-
],
|
|
482
|
-
},
|
|
483
|
-
{
|
|
484
|
-
priority: 120,
|
|
485
|
-
slotPatterns: [/^cart$/i, /shopping cart/i, /\bbasket\b/i],
|
|
486
|
-
queryVariants: ['shopping cart', 'cart', 'basket'],
|
|
487
|
-
iconPreferences: [
|
|
488
|
-
{ pattern: /^shopping[_-]?cart$|^basket$/i, bonus: 220 },
|
|
489
|
-
{ pattern: /shopping-cart-(cog|x|off|discount|dollar|exclamation|heart|minus|pause|plus|question|share|star|bolt|copy|down|up|search|pin)/i, bonus: -260 },
|
|
490
|
-
{ pattern: /basket-(cog|x|off|discount|dollar|exclamation|heart|minus|pause|plus|question|share|star|bolt|copy|down|up|search|pin)/i, bonus: -180 },
|
|
491
|
-
{ pattern: /garden-cart/i, bonus: -180 },
|
|
492
|
-
],
|
|
493
|
-
},
|
|
494
|
-
{
|
|
495
|
-
priority: 90,
|
|
496
|
-
slotPatterns: [/customers?/i, /shoppers?/i, /buyers?/i],
|
|
497
|
-
queryVariants: ['users', 'customers', 'user group'],
|
|
498
|
-
iconPreferences: [
|
|
499
|
-
{ pattern: /^users(?:_|-|$)|(?:_|-)users(?:_|-|$)|users-group|user-group|user-circle|user_circle|^user(?:_|-|$)/i, bonus: 110 },
|
|
500
|
-
{ pattern: /ticket|plane|caret|cancel|\bx\b|off|discount|heart|exclamation|minus|plus|search|share|star|question|bolt|code|copy|dollar|down|up|pin|pause/i, bonus: -120 },
|
|
501
|
-
],
|
|
502
|
-
},
|
|
503
|
-
{
|
|
504
|
-
priority: 90,
|
|
505
|
-
slotPatterns: [/coupons?/i, /discounts?/i, /promo/i, /promotion/i],
|
|
506
|
-
queryVariants: ['coupon', 'tag percent', 'discount', 'percentage'],
|
|
507
|
-
iconPreferences: [
|
|
508
|
-
{ pattern: /coupon|ticket-percent|badge-percent|percent|percentage|tag|shopping-cart-discount|shopping-bag-discount|seal-percent/i, bonus: 120 },
|
|
509
|
-
{ pattern: /^percentage-\d+$|bean|candy|cannabis|off|slash|disabled|alert/i, bonus: -180 },
|
|
510
|
-
],
|
|
511
|
-
},
|
|
512
|
-
{
|
|
513
|
-
priority: 130,
|
|
514
|
-
slotPatterns: [/(cancel|cancelled|canceled|remove|delete)\s+orders?/i, /orders?\s+(cancel|cancelled|canceled|remove|delete)/i],
|
|
515
|
-
queryVariants: ['shopping cart cancel', 'basket cancel', 'cancel order', 'order x'],
|
|
516
|
-
iconPreferences: [
|
|
517
|
-
{ pattern: /cancel|\bx\b|remove|delete|minus|trash/i, bonus: 220 },
|
|
518
|
-
{ pattern: /shopping|cart|basket|package|receipt|clipboard|list/i, bonus: 20 },
|
|
519
|
-
],
|
|
520
|
-
},
|
|
521
|
-
{
|
|
522
|
-
priority: 90,
|
|
523
|
-
slotPatterns: [/orders?/i, /purchases?/i],
|
|
524
|
-
queryVariants: ['package', 'receipt', 'clipboard list', 'shopping bag', 'ordered list'],
|
|
525
|
-
iconPreferences: [
|
|
526
|
-
{ pattern: /^package$|packages|receipt|shopping-bag$|clipboard|list-ordered|file-invoice|file-text/i, bonus: 115 },
|
|
527
|
-
{ pattern: /border|sort|align|cancel|\bx\b|off|discount|heart|exclamation|minus|plus|search|share|star|question|bolt|code|copy|dollar|down|up|pin|pause/i, bonus: -130 },
|
|
528
|
-
],
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
priority: 120,
|
|
532
|
-
slotPatterns: [/shipping/i, /delivery/i, /fulfillment/i, /dispatch/i],
|
|
533
|
-
queryVariants: ['truck delivery', 'delivery', 'shipping', 'package delivery'],
|
|
534
|
-
iconPreferences: [
|
|
535
|
-
{ pattern: /^truck[_-]?delivery$/i, bonus: 260 },
|
|
536
|
-
{ pattern: /^truck$|package[_-]?export|package[_-]?import/i, bonus: 180 },
|
|
537
|
-
{ pattern: /^truck[_-]?return$/i, bonus: -120 },
|
|
538
|
-
{ pattern: /cloud-upload|upload|ship-off|cloud|arrow-up/i, bonus: -220 },
|
|
539
|
-
],
|
|
540
|
-
},
|
|
541
|
-
{
|
|
542
|
-
priority: 120,
|
|
543
|
-
slotPatterns: [/returns?/i, /refunds?/i, /reverse logistics/i],
|
|
544
|
-
queryVariants: ['return', 'refund', 'truck return', 'receipt refund'],
|
|
545
|
-
iconPreferences: [
|
|
546
|
-
{ pattern: /^truck[_-]?return$|receipt[_-]?refund|credit-card[_-]?refund|arrow-back|cash.*move.*back/i, bonus: 220 },
|
|
547
|
-
{ pattern: /player|chevron|stack|upload|cloud|ship-off/i, bonus: -160 },
|
|
548
|
-
],
|
|
549
|
-
},
|
|
550
|
-
{
|
|
551
|
-
priority: 90,
|
|
552
|
-
slotPatterns: [/products?/i, /catalog/i, /inventory/i],
|
|
553
|
-
queryVariants: ['package', 'box', 'tag', 'shopping bag', 'products'],
|
|
554
|
-
iconPreferences: [
|
|
555
|
-
{ pattern: /^package$|packages|package[_-]?\d?|^box$|boxes|tag$|shopping-bag$|warehouse|building-warehouse/i, bonus: 115 },
|
|
556
|
-
{ pattern: /brand-producthunt|brand-stocktwits|border|sort|cancel|\bx\b|off|discount|heart|exclamation|minus|plus|search|share|star|question|bolt|code|copy|dollar|down|up|pin|pause/i, bonus: -130 },
|
|
557
|
-
],
|
|
558
|
-
},
|
|
559
|
-
{
|
|
560
|
-
slotPatterns: [/reports?/i, /analytics/i, /insights?/i],
|
|
561
|
-
queryVariants: ['bar chart', 'file chart', 'analytics chart', 'report document'],
|
|
470
|
+
{
|
|
471
|
+
slotPatterns: [/billing/i, /payment/i, /invoice/i, /subscription/i],
|
|
472
|
+
queryVariants: ['credit card', 'receipt', 'invoice', 'payment', 'wallet'],
|
|
473
|
+
iconPreferences: [
|
|
474
|
+
{ pattern: /credit-card|receipt|wallet|invoice/i, bonus: 44 },
|
|
475
|
+
{ pattern: /card|banknote|currency|dollar/i, bonus: 18 },
|
|
476
|
+
{ pattern: /ruble|franc|lira|bitcoin|yuan/i, bonus: -70 },
|
|
477
|
+
],
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
priority: 90,
|
|
481
|
+
slotPatterns: [/storefront/i, /\bstore\b/i, /\bshop\b/i],
|
|
482
|
+
queryVariants: ['store', 'shop', 'building store', 'shopping bag'],
|
|
483
|
+
iconPreferences: [
|
|
484
|
+
{ pattern: /^store$|^storefront$|building-store|shop[_-]?line|store[_-]?\d?[_-]?line|shopping-bag/i, bonus: 120 },
|
|
485
|
+
{ pattern: /brand-appstore|restore|cancel|\bx\b|off|discount|heart|exclamation|minus|plus|search|share|star|question|bolt|code|copy|dollar|down|up|pin|pause/i, bonus: -120 },
|
|
486
|
+
],
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
priority: 130,
|
|
490
|
+
slotPatterns: [/(store|shop|storefront)\s+(off|disabled|closed|cancelled|canceled)/i, /(off|disabled|closed|cancelled|canceled)\s+(store|shop|storefront)/i],
|
|
491
|
+
queryVariants: ['store off', 'shopping bag x', 'shopping cart off', 'store disabled'],
|
|
492
|
+
iconPreferences: [
|
|
493
|
+
{ pattern: /(store|shop|shopping|bag|cart).*(off|\bx\b|cancel|disabled)|(off|\bx\b|cancel|disabled).*(store|shop|shopping|bag|cart)/i, bonus: 220 },
|
|
494
|
+
{ pattern: /^building-store$|^store$|^shopping-bag$/i, bonus: -70 },
|
|
495
|
+
],
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
priority: 90,
|
|
499
|
+
slotPatterns: [/checkout/i],
|
|
500
|
+
queryVariants: ['shopping cart', 'credit card', 'payment', 'receipt checkout'],
|
|
501
|
+
iconPreferences: [
|
|
502
|
+
{ pattern: /^shopping[_-]?cart$|shopping-cart$|credit-card|card-pay|payment|receipt/i, bonus: 140 },
|
|
503
|
+
{ pattern: /fork|knife|git|branch|merge|forklift|grill|cancel|\bx\b|off|discount|heart|exclamation|minus|plus|search|share|star|question|bolt|code|copy|dollar|down|up|pin|pause/i, bonus: -140 },
|
|
504
|
+
],
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
priority: 120,
|
|
508
|
+
slotPatterns: [/^cart$/i, /shopping cart/i, /\bbasket\b/i],
|
|
509
|
+
queryVariants: ['shopping cart', 'cart', 'basket'],
|
|
510
|
+
iconPreferences: [
|
|
511
|
+
{ pattern: /^shopping[_-]?cart$|^basket$/i, bonus: 220 },
|
|
512
|
+
{ pattern: /shopping-cart-(cog|x|off|discount|dollar|exclamation|heart|minus|pause|plus|question|share|star|bolt|copy|down|up|search|pin)/i, bonus: -260 },
|
|
513
|
+
{ pattern: /basket-(cog|x|off|discount|dollar|exclamation|heart|minus|pause|plus|question|share|star|bolt|copy|down|up|search|pin)/i, bonus: -180 },
|
|
514
|
+
{ pattern: /garden-cart/i, bonus: -180 },
|
|
515
|
+
],
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
priority: 90,
|
|
519
|
+
slotPatterns: [/customers?/i, /shoppers?/i, /buyers?/i],
|
|
520
|
+
queryVariants: ['users', 'customers', 'user group'],
|
|
521
|
+
iconPreferences: [
|
|
522
|
+
{ pattern: /^users(?:_|-|$)|(?:_|-)users(?:_|-|$)|users-group|user-group|user-circle|user_circle|^user(?:_|-|$)/i, bonus: 110 },
|
|
523
|
+
{ pattern: /ticket|plane|caret|cancel|\bx\b|off|discount|heart|exclamation|minus|plus|search|share|star|question|bolt|code|copy|dollar|down|up|pin|pause/i, bonus: -120 },
|
|
524
|
+
],
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
priority: 90,
|
|
528
|
+
slotPatterns: [/coupons?/i, /discounts?/i, /promo/i, /promotion/i],
|
|
529
|
+
queryVariants: ['coupon', 'tag percent', 'discount', 'percentage'],
|
|
530
|
+
iconPreferences: [
|
|
531
|
+
{ pattern: /coupon|ticket-percent|badge-percent|percent|percentage|tag|shopping-cart-discount|shopping-bag-discount|seal-percent/i, bonus: 120 },
|
|
532
|
+
{ pattern: /^percentage-\d+$|bean|candy|cannabis|off|slash|disabled|alert/i, bonus: -180 },
|
|
533
|
+
],
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
priority: 130,
|
|
537
|
+
slotPatterns: [/(cancel|cancelled|canceled|remove|delete)\s+orders?/i, /orders?\s+(cancel|cancelled|canceled|remove|delete)/i],
|
|
538
|
+
queryVariants: ['shopping cart cancel', 'basket cancel', 'cancel order', 'order x'],
|
|
539
|
+
iconPreferences: [
|
|
540
|
+
{ pattern: /cancel|\bx\b|remove|delete|minus|trash/i, bonus: 220 },
|
|
541
|
+
{ pattern: /shopping|cart|basket|package|receipt|clipboard|list/i, bonus: 20 },
|
|
542
|
+
],
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
priority: 90,
|
|
546
|
+
slotPatterns: [/orders?/i, /purchases?/i],
|
|
547
|
+
queryVariants: ['package', 'receipt', 'clipboard list', 'shopping bag', 'ordered list'],
|
|
548
|
+
iconPreferences: [
|
|
549
|
+
{ pattern: /^package$|packages|receipt|shopping-bag$|clipboard|list-ordered|file-invoice|file-text/i, bonus: 115 },
|
|
550
|
+
{ pattern: /border|sort|align|cancel|\bx\b|off|discount|heart|exclamation|minus|plus|search|share|star|question|bolt|code|copy|dollar|down|up|pin|pause/i, bonus: -130 },
|
|
551
|
+
],
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
priority: 120,
|
|
555
|
+
slotPatterns: [/shipping/i, /delivery/i, /fulfillment/i, /dispatch/i],
|
|
556
|
+
queryVariants: ['truck delivery', 'delivery', 'shipping', 'package delivery'],
|
|
557
|
+
iconPreferences: [
|
|
558
|
+
{ pattern: /^truck[_-]?delivery$/i, bonus: 260 },
|
|
559
|
+
{ pattern: /^truck$|package[_-]?export|package[_-]?import/i, bonus: 180 },
|
|
560
|
+
{ pattern: /^truck[_-]?return$/i, bonus: -120 },
|
|
561
|
+
{ pattern: /cloud-upload|upload|ship-off|cloud|arrow-up/i, bonus: -220 },
|
|
562
|
+
],
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
priority: 120,
|
|
566
|
+
slotPatterns: [/returns?/i, /refunds?/i, /reverse logistics/i],
|
|
567
|
+
queryVariants: ['return', 'refund', 'truck return', 'receipt refund'],
|
|
568
|
+
iconPreferences: [
|
|
569
|
+
{ pattern: /^truck[_-]?return$|receipt[_-]?refund|credit-card[_-]?refund|arrow-back|cash.*move.*back/i, bonus: 220 },
|
|
570
|
+
{ pattern: /player|chevron|stack|upload|cloud|ship-off/i, bonus: -160 },
|
|
571
|
+
],
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
priority: 90,
|
|
575
|
+
slotPatterns: [/products?/i, /catalog/i, /inventory/i],
|
|
576
|
+
queryVariants: ['package', 'box', 'tag', 'shopping bag', 'products'],
|
|
577
|
+
iconPreferences: [
|
|
578
|
+
{ pattern: /^package$|packages|package[_-]?\d?|^box$|boxes|tag$|shopping-bag$|warehouse|building-warehouse/i, bonus: 115 },
|
|
579
|
+
{ pattern: /brand-producthunt|brand-stocktwits|border|sort|cancel|\bx\b|off|discount|heart|exclamation|minus|plus|search|share|star|question|bolt|code|copy|dollar|down|up|pin|pause/i, bonus: -130 },
|
|
580
|
+
],
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
slotPatterns: [/reports?/i, /analytics/i, /insights?/i],
|
|
584
|
+
queryVariants: ['bar chart', 'file chart', 'analytics chart', 'report document'],
|
|
562
585
|
iconPreferences: [
|
|
563
586
|
{ pattern: /file-.*chart|chart-bar|bar-chart-3|bar-chart|chart-line|line-chart/i, bonus: 40 },
|
|
564
|
-
{ pattern: /chart|report|analytics/i, bonus: 16 },
|
|
565
|
-
],
|
|
566
|
-
},
|
|
567
|
-
{
|
|
568
|
-
priority: 100,
|
|
569
|
-
slotPatterns: [/^quotes?$/i, /blockquote/i, /quotation/i, /citation/i],
|
|
570
|
-
queryVariants: ['quotes', 'quotation', 'quote', 'blockquote'],
|
|
571
|
-
iconPreferences: [
|
|
572
|
-
{ pattern: /^quotes?$|quotation|blockquote/i, bonus: 180 },
|
|
573
|
-
{ pattern: /indent|text-align|receipt|ticket/i, bonus: -120 },
|
|
574
|
-
],
|
|
575
|
-
},
|
|
576
|
-
{
|
|
577
|
-
slotPatterns: [/settings?/i, /preferences?/i, /configure/i],
|
|
578
|
-
queryVariants: ['settings', 'cog', 'sliders'],
|
|
587
|
+
{ pattern: /chart|report|analytics/i, bonus: 16 },
|
|
588
|
+
],
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
priority: 100,
|
|
592
|
+
slotPatterns: [/^quotes?$/i, /blockquote/i, /quotation/i, /citation/i],
|
|
593
|
+
queryVariants: ['quotes', 'quotation', 'quote', 'blockquote'],
|
|
594
|
+
iconPreferences: [
|
|
595
|
+
{ pattern: /^quotes?$|quotation|blockquote/i, bonus: 180 },
|
|
596
|
+
{ pattern: /indent|text-align|receipt|ticket/i, bonus: -120 },
|
|
597
|
+
],
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
slotPatterns: [/settings?/i, /preferences?/i, /configure/i],
|
|
601
|
+
queryVariants: ['settings', 'cog', 'sliders'],
|
|
579
602
|
iconPreferences: [
|
|
580
603
|
{ pattern: /^settings$|^cog$|settings-2|sliders/i, bonus: 34 },
|
|
581
|
-
{ pattern: /settings|cog|adjustments/i, bonus: 16 },
|
|
582
|
-
],
|
|
583
|
-
},
|
|
584
|
-
{
|
|
585
|
-
priority: 90,
|
|
586
|
-
slotPatterns: [/permissions?/i, /access control/i, /roles?/i],
|
|
587
|
-
queryVariants: ['user key', 'shield lock', 'key', 'settings permissions'],
|
|
588
|
-
iconPreferences: [
|
|
589
|
-
{ pattern: /user-key|user-lock|user-check|key|lock|shield|adjustments|settings/i, bonus: 120 },
|
|
590
|
-
{ pattern: /free-rights|premium-rights|icons$/i, bonus: -100 },
|
|
591
|
-
],
|
|
592
|
-
},
|
|
593
|
-
{
|
|
594
|
-
slotPatterns: [/database/i, /storage/i],
|
|
595
|
-
queryVariants: ['database', 'server database', 'data storage'],
|
|
596
|
-
iconPreferences: [
|
|
597
|
-
{ pattern: /^database$|database-stack/i, bonus: 36 },
|
|
598
|
-
{ pattern: /database|server/i, bonus: 16 },
|
|
599
|
-
],
|
|
600
|
-
},
|
|
601
|
-
{
|
|
602
|
-
slotPatterns: [/search/i, /find/i, /lookup/i],
|
|
603
|
-
queryVariants: ['search', 'find', 'magnifier', 'magnifying glass'],
|
|
604
|
-
iconPreferences: [
|
|
605
|
-
{ pattern: /^search$/i, bonus: 140 },
|
|
606
|
-
{ pattern: /^search(?:_|-|$)|(?:_|-)search(?:_|-|$)/i, bonus: 64 },
|
|
607
|
-
{ pattern: /magnifier|magnifying/i, bonus: 36 },
|
|
608
|
-
{ pattern: /file-search|folder-search|scan-search|mail-search|calendar-search/i, bonus: -90 },
|
|
609
|
-
],
|
|
610
|
-
},
|
|
611
|
-
{
|
|
612
|
-
priority: 115,
|
|
613
|
-
slotPatterns: [/\b(add|new|create)\s+bookmark\b/i, /\bbookmark\s+(add|new|create)\b/i],
|
|
614
|
-
queryVariants: ['bookmark add', 'add bookmark', 'bookmark plus'],
|
|
615
|
-
iconPreferences: [
|
|
616
|
-
{ pattern: /^bookmark[_-]?(add|plus)(?:_|-|$)|(?:_|-)bookmark[_-]?(add|plus)(?:_|-|$)/i, bonus: 220 },
|
|
617
|
-
{ pattern: /^bookmarks?(?:_|-|$)|(?:_|-)bookmarks?(?:_|-|$)/i, bonus: 46 },
|
|
618
|
-
{ pattern: /^(add|plus)(?:_|-|$)/i, bonus: -80 },
|
|
619
|
-
],
|
|
620
|
-
},
|
|
621
|
-
{
|
|
622
|
-
priority: 115,
|
|
623
|
-
slotPatterns: [/\bedit\s+bookmark\b/i, /\bbookmark\s+edit\b/i],
|
|
624
|
-
queryVariants: ['bookmark edit', 'edit bookmark', 'bookmark pencil'],
|
|
625
|
-
iconPreferences: [
|
|
626
|
-
{ pattern: /^bookmark[_-]?edit(?:_|-|$)|(?:_|-)bookmark[_-]?edit(?:_|-|$)/i, bonus: 190 },
|
|
627
|
-
{ pattern: /^bookmarks?(?:_|-|$)|(?:_|-)bookmarks?(?:_|-|$)/i, bonus: 46 },
|
|
628
|
-
{ pattern: /^edit(?:_|-|$)|pencil/i, bonus: -70 },
|
|
629
|
-
],
|
|
630
|
-
},
|
|
631
|
-
{
|
|
632
|
-
priority: 115,
|
|
633
|
-
slotPatterns: [/\b(remove|delete)\s+bookmark\b/i, /\bbookmark\s+(remove|delete)\b/i],
|
|
634
|
-
queryVariants: ['bookmark remove', 'remove bookmark', 'bookmark minus'],
|
|
635
|
-
iconPreferences: [
|
|
636
|
-
{ pattern: /^bookmark[_-]?(remove|minus|x)(?:_|-|$)|(?:_|-)bookmark[_-]?(remove|minus|x)(?:_|-|$)/i, bonus: 190 },
|
|
637
|
-
{ pattern: /^bookmarks?(?:_|-|$)|(?:_|-)bookmarks?(?:_|-|$)/i, bonus: 46 },
|
|
638
|
-
{ pattern: /^(remove|delete|minus)(?:_|-|$)/i, bonus: -70 },
|
|
639
|
-
],
|
|
640
|
-
},
|
|
641
|
-
{
|
|
642
|
-
slotPatterns: [/bookmark/i, /saved?/i, /save article/i],
|
|
643
|
-
queryVariants: ['bookmark', 'saved', 'save'],
|
|
644
|
-
iconPreferences: [
|
|
645
|
-
{ pattern: /^bookmarks?(?:_|-|$)|(?:_|-)bookmarks?(?:_|-|$)/i, bonus: 66 },
|
|
646
|
-
{ pattern: /save|favorite|star/i, bonus: 14 },
|
|
647
|
-
],
|
|
648
|
-
},
|
|
649
|
-
{
|
|
650
|
-
slotPatterns: [/share/i, /send article/i, /forward/i],
|
|
651
|
-
queryVariants: ['share', 'send', 'forward'],
|
|
652
|
-
iconPreferences: [
|
|
653
|
-
{ pattern: /^share(?:_|-|$)|(?:_|-)share(?:_|-|$)/i, bonus: 58 },
|
|
654
|
-
{ pattern: /send|forward/i, bonus: 18 },
|
|
655
|
-
],
|
|
656
|
-
},
|
|
657
|
-
{
|
|
658
|
-
priority: 110,
|
|
659
|
-
slotPatterns: [/previous page/i, /previous/i, /\bback\b/i, /go back/i],
|
|
660
|
-
queryVariants: ['arrow left', 'chevron left', 'back arrow', 'previous'],
|
|
661
|
-
iconPreferences: [
|
|
662
|
-
{ pattern: /^arrow[_-]?left$|^chevron[_-]?left$|^caret[_-]?left$|arrow[_-]?back$|back[_-]?line|arrow[_-]?to[_-]?left|left(?:_|-|$)/i, bonus: 140 },
|
|
663
|
-
{ pattern: /skip-back|step-back/i, bonus: 48 },
|
|
664
|
-
{ pattern: /send-to-back|file|archive|audio|floppy|cash|banknote|brand|copy/i, bonus: -140 },
|
|
665
|
-
],
|
|
666
|
-
},
|
|
667
|
-
{
|
|
668
|
-
priority: 90,
|
|
669
|
-
slotPatterns: [/read more/i, /more link/i, /continue/i, /open article/i, /next page/i, /^next$/i],
|
|
670
|
-
queryVariants: ['arrow right', 'move right', 'chevron right', 'read more', 'next'],
|
|
671
|
-
iconPreferences: [
|
|
672
|
-
{ pattern: /^arrow[_-]?right$|^move[_-]?right$|arrow[_-]?to[_-]?right|chevron[_-]?right|right(?:_|-|$)/i, bonus: 90 },
|
|
673
|
-
{ pattern: /square|circle|corner|up|down|left|banknote|archive/i, bonus: -70 },
|
|
674
|
-
],
|
|
675
|
-
},
|
|
676
|
-
{
|
|
677
|
-
slotPatterns: [/categor(?:y|ies)/i, /chips?/i, /filter/i, /topics?/i, /tags?/i],
|
|
678
|
-
queryVariants: ['filter', 'category', 'tag', 'grid'],
|
|
679
|
-
iconPreferences: [
|
|
680
|
-
{ pattern: /^filter(?:_|-|$)|(?:_|-)filter(?:_|-|$)/i, bonus: 56 },
|
|
681
|
-
{ pattern: /^tag(?:_|-|$)|(?:_|-)tag(?:_|-|$)|category|grid/i, bonus: 26 },
|
|
682
|
-
],
|
|
683
|
-
},
|
|
684
|
-
{
|
|
685
|
-
slotPatterns: [/trending/i, /popular/i, /top stories/i, /hot/i],
|
|
686
|
-
queryVariants: ['trending up', 'chart up', 'fire', 'popular'],
|
|
687
|
-
iconPreferences: [
|
|
688
|
-
{ pattern: /^trending[_-]?up(?:_|-|$)|chart.*up|up.*chart/i, bonus: 62 },
|
|
689
|
-
{ pattern: /^fire(?:_|-|$)|flame|hot/i, bonus: 22 },
|
|
690
|
-
],
|
|
691
|
-
},
|
|
692
|
-
{
|
|
693
|
-
slotPatterns: [/news/i, /article/i, /headline/i, /story/i, /publisher/i, /logo/i, /title/i],
|
|
694
|
-
queryVariants: ['news', 'article', 'newspaper', 'headline'],
|
|
695
|
-
iconPreferences: [
|
|
696
|
-
{ pattern: /^news(?:_|-|$)|(?:_|-)news(?:_|-|$)|newspaper|article/i, bonus: 66 },
|
|
697
|
-
{ pattern: /file|document|paper/i, bonus: 16 },
|
|
698
|
-
],
|
|
699
|
-
},
|
|
700
|
-
{
|
|
701
|
-
slotPatterns: [/dashboard/i],
|
|
702
|
-
queryVariants: ['dashboard', 'layout dashboard', 'grid dashboard'],
|
|
703
|
-
iconPreferences: [
|
|
704
|
-
{ pattern: /^dashboard$|layout-dashboard|dashboard/i, bonus: 50 },
|
|
705
|
-
{ pattern: /grid|layout/i, bonus: 12 },
|
|
706
|
-
],
|
|
707
|
-
},
|
|
708
|
-
{
|
|
709
|
-
slotPatterns: [/projects?/i],
|
|
710
|
-
queryVariants: ['folder', 'folders', 'project folder'],
|
|
711
|
-
iconPreferences: [
|
|
712
|
-
{ pattern: /^folders?$|(?:_|-)folders?(?:_|-|$)/i, bonus: 56 },
|
|
713
|
-
{ pattern: /briefcase|project/i, bonus: 12 },
|
|
714
|
-
],
|
|
715
|
-
},
|
|
716
|
-
{
|
|
717
|
-
slotPatterns: [/tasks?/i, /todo/i, /to do/i, /checklist/i],
|
|
718
|
-
queryVariants: ['list check', 'checklist', 'checkbox', 'task'],
|
|
719
|
-
iconPreferences: [
|
|
720
|
-
{ pattern: /list-check|list_check|checkbox|checklist|clipboard-check/i, bonus: 56 },
|
|
721
|
-
{ pattern: /check|task/i, bonus: 16 },
|
|
722
|
-
],
|
|
723
|
-
},
|
|
724
|
-
{
|
|
725
|
-
slotPatterns: [/team/i, /\busers\b/i, /members?/i],
|
|
726
|
-
queryVariants: ['users', 'team', 'user group'],
|
|
727
|
-
iconPreferences: [
|
|
728
|
-
{ pattern: /^users(?:_|-|$)|(?:_|-)users(?:_|-|$)|user-group|user_circle|user-circle/i, bonus: 64 },
|
|
729
|
-
{ pattern: /^user(?:_|-|$)|(?:_|-)user(?:_|-|$)/i, bonus: 18 },
|
|
730
|
-
],
|
|
731
|
-
},
|
|
732
|
-
{
|
|
733
|
-
slotPatterns: [/calendar/i, /schedule/i, /events?/i],
|
|
734
|
-
queryVariants: ['calendar', 'calendar event', 'schedule'],
|
|
735
|
-
iconPreferences: [
|
|
736
|
-
{ pattern: /^calendar(?:_|-|$)|(?:_|-)calendar(?:_|-|$)/i, bonus: 54 },
|
|
737
|
-
{ pattern: /event|schedule/i, bonus: 18 },
|
|
738
|
-
],
|
|
739
|
-
},
|
|
740
|
-
{
|
|
741
|
-
slotPatterns: [/\bbold\b/i],
|
|
742
|
-
queryVariants: ['text b', 'bold', 'text bold'],
|
|
743
|
-
iconPreferences: [
|
|
744
|
-
{ pattern: /^text[_-]?b$|text-bold|bold/i, bonus: 66 },
|
|
745
|
-
],
|
|
746
|
-
},
|
|
747
|
-
{
|
|
748
|
-
slotPatterns: [/italic/i],
|
|
749
|
-
queryVariants: ['text italic', 'italic'],
|
|
750
|
-
iconPreferences: [
|
|
751
|
-
{ pattern: /^text[_-]?italic$|italic/i, bonus: 66 },
|
|
752
|
-
],
|
|
753
|
-
},
|
|
754
|
-
{
|
|
755
|
-
priority: 130,
|
|
756
|
-
slotPatterns: [/broken\s+link/i, /link\s+(broken|break|disabled|off)/i],
|
|
757
|
-
queryVariants: ['broken link', 'link break', 'link slash'],
|
|
758
|
-
iconPreferences: [
|
|
759
|
-
{ pattern: /link.*(break|broken|slash|off)|(break|broken|slash|off).*link/i, bonus: 180 },
|
|
760
|
-
{ pattern: /^link(?:_|-|$)|(?:_|-)link(?:_|-|$)/i, bonus: 10 },
|
|
761
|
-
],
|
|
762
|
-
},
|
|
763
|
-
{
|
|
764
|
-
priority: 130,
|
|
765
|
-
slotPatterns: [/(broken|disabled|off)\s+(image|photo|picture)/i, /(image|photo|picture)\s+(broken|disabled|off)/i],
|
|
766
|
-
queryVariants: ['photo off', 'image off', 'broken image', 'image broken'],
|
|
767
|
-
iconPreferences: [
|
|
768
|
-
{ pattern: /(image|photo|picture).*(broken|off|slash)|(broken|off|slash).*(image|photo|picture)/i, bonus: 240 },
|
|
769
|
-
{ pattern: /^image(?:_|-|$)|(?:_|-)image(?:_|-|$)|picture|photo/i, bonus: 10 },
|
|
770
|
-
],
|
|
771
|
-
},
|
|
772
|
-
{
|
|
773
|
-
priority: 130,
|
|
774
|
-
slotPatterns: [/(comments?|chat|discussion)\s+(off|disabled|muted|slash)/i, /(off|disabled|muted|slash)\s+(comments?|chat|discussion)/i],
|
|
775
|
-
queryVariants: ['chat slash', 'comment off', 'comments off', 'message slash'],
|
|
776
|
-
iconPreferences: [
|
|
777
|
-
{ pattern: /(chat|comment|message).*(slash|off|x)|(slash|off|x).*(chat|comment|message)/i, bonus: 180 },
|
|
778
|
-
{ pattern: /chat|comment|message/i, bonus: 10 },
|
|
779
|
-
],
|
|
780
|
-
},
|
|
781
|
-
{
|
|
782
|
-
slotPatterns: [/\blink\b/i, /hyperlink/i],
|
|
783
|
-
queryVariants: ['link', 'link simple', 'hyperlink'],
|
|
784
|
-
iconPreferences: [
|
|
785
|
-
{ pattern: /^link(?:_|-|$)|(?:_|-)link(?:_|-|$)/i, bonus: 56 },
|
|
786
|
-
{ pattern: /chain/i, bonus: 14 },
|
|
787
|
-
{ pattern: /break|broken|slash|unlink|brand/i, bonus: -120 },
|
|
788
|
-
],
|
|
789
|
-
},
|
|
790
|
-
{
|
|
791
|
-
slotPatterns: [/image/i, /photo/i, /picture/i],
|
|
792
|
-
queryVariants: ['image', 'picture', 'photo'],
|
|
793
|
-
iconPreferences: [
|
|
794
|
-
{ pattern: /^image(?:_|-|$)|(?:_|-)image(?:_|-|$)|picture|photo/i, bonus: 56 },
|
|
795
|
-
{ pattern: /broken|off|slash|brand/i, bonus: -120 },
|
|
796
|
-
],
|
|
797
|
-
},
|
|
798
|
-
{
|
|
799
|
-
priority: 80,
|
|
800
|
-
slotPatterns: [/comments?/i, /chat/i, /discussion/i],
|
|
801
|
-
queryVariants: ['chat text', 'comments', 'message dots'],
|
|
802
|
-
iconPreferences: [
|
|
803
|
-
{ pattern: /chat|comment|message/i, bonus: 76 },
|
|
804
|
-
{ pattern: /slash|off|x$|brand/i, bonus: -120 },
|
|
805
|
-
],
|
|
806
|
-
},
|
|
807
|
-
{
|
|
808
|
-
slotPatterns: [/undo/i],
|
|
809
|
-
queryVariants: ['undo', 'arrow counter clockwise', 'rotate left'],
|
|
810
|
-
iconPreferences: [
|
|
811
|
-
{ pattern: /^undo$|arrow-counter-clockwise|arrow_counter_clockwise|rotate.*left/i, bonus: 66 },
|
|
812
|
-
{ pattern: /^redo$|^arrows?[_-]clockwise$|clock[_-]clockwise|arrow_clockwise|rotate.*right/i, bonus: -120 },
|
|
813
|
-
],
|
|
814
|
-
},
|
|
815
|
-
{
|
|
816
|
-
slotPatterns: [/redo/i],
|
|
817
|
-
queryVariants: ['redo', 'arrow clockwise', 'rotate right'],
|
|
818
|
-
iconPreferences: [
|
|
819
|
-
{ pattern: /^redo$|arrow-clockwise|arrow_clockwise|rotate.*right/i, bonus: 66 },
|
|
820
|
-
{ pattern: /^undo$|^arrows?[_-]counter[_-]clockwise$|clock[_-]counter[_-]clockwise|arrow_counter_clockwise|rotate.*left/i, bonus: -120 },
|
|
821
|
-
],
|
|
822
|
-
},
|
|
823
|
-
]);
|
|
604
|
+
{ pattern: /settings|cog|adjustments/i, bonus: 16 },
|
|
605
|
+
],
|
|
606
|
+
},
|
|
607
|
+
{
|
|
608
|
+
priority: 90,
|
|
609
|
+
slotPatterns: [/permissions?/i, /access control/i, /roles?/i],
|
|
610
|
+
queryVariants: ['user key', 'shield lock', 'key', 'settings permissions'],
|
|
611
|
+
iconPreferences: [
|
|
612
|
+
{ pattern: /user-key|user-lock|user-check|key|lock|shield|adjustments|settings/i, bonus: 120 },
|
|
613
|
+
{ pattern: /free-rights|premium-rights|icons$/i, bonus: -100 },
|
|
614
|
+
],
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
slotPatterns: [/database/i, /storage/i],
|
|
618
|
+
queryVariants: ['database', 'server database', 'data storage'],
|
|
619
|
+
iconPreferences: [
|
|
620
|
+
{ pattern: /^database$|database-stack/i, bonus: 36 },
|
|
621
|
+
{ pattern: /database|server/i, bonus: 16 },
|
|
622
|
+
],
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
slotPatterns: [/search/i, /find/i, /lookup/i],
|
|
626
|
+
queryVariants: ['search', 'find', 'magnifier', 'magnifying glass'],
|
|
627
|
+
iconPreferences: [
|
|
628
|
+
{ pattern: /^search$/i, bonus: 140 },
|
|
629
|
+
{ pattern: /^search(?:_|-|$)|(?:_|-)search(?:_|-|$)/i, bonus: 64 },
|
|
630
|
+
{ pattern: /magnifier|magnifying/i, bonus: 36 },
|
|
631
|
+
{ pattern: /file-search|folder-search|scan-search|mail-search|calendar-search/i, bonus: -90 },
|
|
632
|
+
],
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
priority: 115,
|
|
636
|
+
slotPatterns: [/\b(add|new|create)\s+bookmark\b/i, /\bbookmark\s+(add|new|create)\b/i],
|
|
637
|
+
queryVariants: ['bookmark add', 'add bookmark', 'bookmark plus'],
|
|
638
|
+
iconPreferences: [
|
|
639
|
+
{ pattern: /^bookmark[_-]?(add|plus)(?:_|-|$)|(?:_|-)bookmark[_-]?(add|plus)(?:_|-|$)/i, bonus: 220 },
|
|
640
|
+
{ pattern: /^bookmarks?(?:_|-|$)|(?:_|-)bookmarks?(?:_|-|$)/i, bonus: 46 },
|
|
641
|
+
{ pattern: /^(add|plus)(?:_|-|$)/i, bonus: -80 },
|
|
642
|
+
],
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
priority: 115,
|
|
646
|
+
slotPatterns: [/\bedit\s+bookmark\b/i, /\bbookmark\s+edit\b/i],
|
|
647
|
+
queryVariants: ['bookmark edit', 'edit bookmark', 'bookmark pencil'],
|
|
648
|
+
iconPreferences: [
|
|
649
|
+
{ pattern: /^bookmark[_-]?edit(?:_|-|$)|(?:_|-)bookmark[_-]?edit(?:_|-|$)/i, bonus: 190 },
|
|
650
|
+
{ pattern: /^bookmarks?(?:_|-|$)|(?:_|-)bookmarks?(?:_|-|$)/i, bonus: 46 },
|
|
651
|
+
{ pattern: /^edit(?:_|-|$)|pencil/i, bonus: -70 },
|
|
652
|
+
],
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
priority: 115,
|
|
656
|
+
slotPatterns: [/\b(remove|delete)\s+bookmark\b/i, /\bbookmark\s+(remove|delete)\b/i],
|
|
657
|
+
queryVariants: ['bookmark remove', 'remove bookmark', 'bookmark minus'],
|
|
658
|
+
iconPreferences: [
|
|
659
|
+
{ pattern: /^bookmark[_-]?(remove|minus|x)(?:_|-|$)|(?:_|-)bookmark[_-]?(remove|minus|x)(?:_|-|$)/i, bonus: 190 },
|
|
660
|
+
{ pattern: /^bookmarks?(?:_|-|$)|(?:_|-)bookmarks?(?:_|-|$)/i, bonus: 46 },
|
|
661
|
+
{ pattern: /^(remove|delete|minus)(?:_|-|$)/i, bonus: -70 },
|
|
662
|
+
],
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
slotPatterns: [/bookmark/i, /saved?/i, /save article/i],
|
|
666
|
+
queryVariants: ['bookmark', 'saved', 'save'],
|
|
667
|
+
iconPreferences: [
|
|
668
|
+
{ pattern: /^bookmarks?(?:_|-|$)|(?:_|-)bookmarks?(?:_|-|$)/i, bonus: 66 },
|
|
669
|
+
{ pattern: /save|favorite|star/i, bonus: 14 },
|
|
670
|
+
],
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
slotPatterns: [/share/i, /send article/i, /forward/i],
|
|
674
|
+
queryVariants: ['share', 'send', 'forward'],
|
|
675
|
+
iconPreferences: [
|
|
676
|
+
{ pattern: /^share(?:_|-|$)|(?:_|-)share(?:_|-|$)/i, bonus: 58 },
|
|
677
|
+
{ pattern: /send|forward/i, bonus: 18 },
|
|
678
|
+
],
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
priority: 110,
|
|
682
|
+
slotPatterns: [/previous page/i, /previous/i, /\bback\b/i, /go back/i],
|
|
683
|
+
queryVariants: ['arrow left', 'chevron left', 'back arrow', 'previous'],
|
|
684
|
+
iconPreferences: [
|
|
685
|
+
{ pattern: /^arrow[_-]?left$|^chevron[_-]?left$|^caret[_-]?left$|arrow[_-]?back$|back[_-]?line|arrow[_-]?to[_-]?left|left(?:_|-|$)/i, bonus: 140 },
|
|
686
|
+
{ pattern: /skip-back|step-back/i, bonus: 48 },
|
|
687
|
+
{ pattern: /send-to-back|file|archive|audio|floppy|cash|banknote|brand|copy/i, bonus: -140 },
|
|
688
|
+
],
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
priority: 90,
|
|
692
|
+
slotPatterns: [/read more/i, /more link/i, /continue/i, /open article/i, /next page/i, /^next$/i],
|
|
693
|
+
queryVariants: ['arrow right', 'move right', 'chevron right', 'read more', 'next'],
|
|
694
|
+
iconPreferences: [
|
|
695
|
+
{ pattern: /^arrow[_-]?right$|^move[_-]?right$|arrow[_-]?to[_-]?right|chevron[_-]?right|right(?:_|-|$)/i, bonus: 90 },
|
|
696
|
+
{ pattern: /square|circle|corner|up|down|left|banknote|archive/i, bonus: -70 },
|
|
697
|
+
],
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
slotPatterns: [/categor(?:y|ies)/i, /chips?/i, /filter/i, /topics?/i, /tags?/i],
|
|
701
|
+
queryVariants: ['filter', 'category', 'tag', 'grid'],
|
|
702
|
+
iconPreferences: [
|
|
703
|
+
{ pattern: /^filter(?:_|-|$)|(?:_|-)filter(?:_|-|$)/i, bonus: 56 },
|
|
704
|
+
{ pattern: /^tag(?:_|-|$)|(?:_|-)tag(?:_|-|$)|category|grid/i, bonus: 26 },
|
|
705
|
+
],
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
slotPatterns: [/trending/i, /popular/i, /top stories/i, /hot/i],
|
|
709
|
+
queryVariants: ['trending up', 'chart up', 'fire', 'popular'],
|
|
710
|
+
iconPreferences: [
|
|
711
|
+
{ pattern: /^trending[_-]?up(?:_|-|$)|chart.*up|up.*chart/i, bonus: 62 },
|
|
712
|
+
{ pattern: /^fire(?:_|-|$)|flame|hot/i, bonus: 22 },
|
|
713
|
+
],
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
slotPatterns: [/news/i, /article/i, /headline/i, /story/i, /publisher/i, /logo/i, /title/i],
|
|
717
|
+
queryVariants: ['news', 'article', 'newspaper', 'headline'],
|
|
718
|
+
iconPreferences: [
|
|
719
|
+
{ pattern: /^news(?:_|-|$)|(?:_|-)news(?:_|-|$)|newspaper|article/i, bonus: 66 },
|
|
720
|
+
{ pattern: /file|document|paper/i, bonus: 16 },
|
|
721
|
+
],
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
slotPatterns: [/dashboard/i],
|
|
725
|
+
queryVariants: ['dashboard', 'layout dashboard', 'grid dashboard'],
|
|
726
|
+
iconPreferences: [
|
|
727
|
+
{ pattern: /^dashboard$|layout-dashboard|dashboard/i, bonus: 50 },
|
|
728
|
+
{ pattern: /grid|layout/i, bonus: 12 },
|
|
729
|
+
],
|
|
730
|
+
},
|
|
731
|
+
{
|
|
732
|
+
slotPatterns: [/projects?/i],
|
|
733
|
+
queryVariants: ['folder', 'folders', 'project folder'],
|
|
734
|
+
iconPreferences: [
|
|
735
|
+
{ pattern: /^folders?$|(?:_|-)folders?(?:_|-|$)/i, bonus: 56 },
|
|
736
|
+
{ pattern: /briefcase|project/i, bonus: 12 },
|
|
737
|
+
],
|
|
738
|
+
},
|
|
739
|
+
{
|
|
740
|
+
slotPatterns: [/tasks?/i, /todo/i, /to do/i, /checklist/i],
|
|
741
|
+
queryVariants: ['list check', 'checklist', 'checkbox', 'task'],
|
|
742
|
+
iconPreferences: [
|
|
743
|
+
{ pattern: /list-check|list_check|checkbox|checklist|clipboard-check/i, bonus: 56 },
|
|
744
|
+
{ pattern: /check|task/i, bonus: 16 },
|
|
745
|
+
],
|
|
746
|
+
},
|
|
747
|
+
{
|
|
748
|
+
slotPatterns: [/team/i, /\busers\b/i, /members?/i],
|
|
749
|
+
queryVariants: ['users', 'team', 'user group'],
|
|
750
|
+
iconPreferences: [
|
|
751
|
+
{ pattern: /^users(?:_|-|$)|(?:_|-)users(?:_|-|$)|user-group|user_circle|user-circle/i, bonus: 64 },
|
|
752
|
+
{ pattern: /^user(?:_|-|$)|(?:_|-)user(?:_|-|$)/i, bonus: 18 },
|
|
753
|
+
],
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
slotPatterns: [/calendar/i, /schedule/i, /events?/i],
|
|
757
|
+
queryVariants: ['calendar', 'calendar event', 'schedule'],
|
|
758
|
+
iconPreferences: [
|
|
759
|
+
{ pattern: /^calendar(?:_|-|$)|(?:_|-)calendar(?:_|-|$)/i, bonus: 54 },
|
|
760
|
+
{ pattern: /event|schedule/i, bonus: 18 },
|
|
761
|
+
],
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
slotPatterns: [/\bbold\b/i],
|
|
765
|
+
queryVariants: ['text b', 'bold', 'text bold'],
|
|
766
|
+
iconPreferences: [
|
|
767
|
+
{ pattern: /^text[_-]?b$|text-bold|bold/i, bonus: 66 },
|
|
768
|
+
],
|
|
769
|
+
},
|
|
770
|
+
{
|
|
771
|
+
slotPatterns: [/italic/i],
|
|
772
|
+
queryVariants: ['text italic', 'italic'],
|
|
773
|
+
iconPreferences: [
|
|
774
|
+
{ pattern: /^text[_-]?italic$|italic/i, bonus: 66 },
|
|
775
|
+
],
|
|
776
|
+
},
|
|
777
|
+
{
|
|
778
|
+
priority: 130,
|
|
779
|
+
slotPatterns: [/broken\s+link/i, /link\s+(broken|break|disabled|off)/i],
|
|
780
|
+
queryVariants: ['broken link', 'link break', 'link slash'],
|
|
781
|
+
iconPreferences: [
|
|
782
|
+
{ pattern: /link.*(break|broken|slash|off)|(break|broken|slash|off).*link/i, bonus: 180 },
|
|
783
|
+
{ pattern: /^link(?:_|-|$)|(?:_|-)link(?:_|-|$)/i, bonus: 10 },
|
|
784
|
+
],
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
priority: 130,
|
|
788
|
+
slotPatterns: [/(broken|disabled|off)\s+(image|photo|picture)/i, /(image|photo|picture)\s+(broken|disabled|off)/i],
|
|
789
|
+
queryVariants: ['photo off', 'image off', 'broken image', 'image broken'],
|
|
790
|
+
iconPreferences: [
|
|
791
|
+
{ pattern: /(image|photo|picture).*(broken|off|slash)|(broken|off|slash).*(image|photo|picture)/i, bonus: 240 },
|
|
792
|
+
{ pattern: /^image(?:_|-|$)|(?:_|-)image(?:_|-|$)|picture|photo/i, bonus: 10 },
|
|
793
|
+
],
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
priority: 130,
|
|
797
|
+
slotPatterns: [/(comments?|chat|discussion)\s+(off|disabled|muted|slash)/i, /(off|disabled|muted|slash)\s+(comments?|chat|discussion)/i],
|
|
798
|
+
queryVariants: ['chat slash', 'comment off', 'comments off', 'message slash'],
|
|
799
|
+
iconPreferences: [
|
|
800
|
+
{ pattern: /(chat|comment|message).*(slash|off|x)|(slash|off|x).*(chat|comment|message)/i, bonus: 180 },
|
|
801
|
+
{ pattern: /chat|comment|message/i, bonus: 10 },
|
|
802
|
+
],
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
slotPatterns: [/\blink\b/i, /hyperlink/i],
|
|
806
|
+
queryVariants: ['link', 'link simple', 'hyperlink'],
|
|
807
|
+
iconPreferences: [
|
|
808
|
+
{ pattern: /^link(?:_|-|$)|(?:_|-)link(?:_|-|$)/i, bonus: 56 },
|
|
809
|
+
{ pattern: /chain/i, bonus: 14 },
|
|
810
|
+
{ pattern: /break|broken|slash|unlink|brand/i, bonus: -120 },
|
|
811
|
+
],
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
slotPatterns: [/image/i, /photo/i, /picture/i],
|
|
815
|
+
queryVariants: ['image', 'picture', 'photo'],
|
|
816
|
+
iconPreferences: [
|
|
817
|
+
{ pattern: /^image(?:_|-|$)|(?:_|-)image(?:_|-|$)|picture|photo/i, bonus: 56 },
|
|
818
|
+
{ pattern: /broken|off|slash|brand/i, bonus: -120 },
|
|
819
|
+
],
|
|
820
|
+
},
|
|
821
|
+
{
|
|
822
|
+
priority: 80,
|
|
823
|
+
slotPatterns: [/comments?/i, /chat/i, /discussion/i],
|
|
824
|
+
queryVariants: ['chat text', 'comments', 'message dots'],
|
|
825
|
+
iconPreferences: [
|
|
826
|
+
{ pattern: /chat|comment|message/i, bonus: 76 },
|
|
827
|
+
{ pattern: /slash|off|x$|brand/i, bonus: -120 },
|
|
828
|
+
],
|
|
829
|
+
},
|
|
830
|
+
{
|
|
831
|
+
slotPatterns: [/undo/i],
|
|
832
|
+
queryVariants: ['undo', 'arrow counter clockwise', 'rotate left'],
|
|
833
|
+
iconPreferences: [
|
|
834
|
+
{ pattern: /^undo$|arrow-counter-clockwise|arrow_counter_clockwise|rotate.*left/i, bonus: 66 },
|
|
835
|
+
{ pattern: /^redo$|^arrows?[_-]clockwise$|clock[_-]clockwise|arrow_clockwise|rotate.*right/i, bonus: -120 },
|
|
836
|
+
],
|
|
837
|
+
},
|
|
838
|
+
{
|
|
839
|
+
slotPatterns: [/redo/i],
|
|
840
|
+
queryVariants: ['redo', 'arrow clockwise', 'rotate right'],
|
|
841
|
+
iconPreferences: [
|
|
842
|
+
{ pattern: /^redo$|arrow-clockwise|arrow_clockwise|rotate.*right/i, bonus: 66 },
|
|
843
|
+
{ pattern: /^undo$|^arrows?[_-]counter[_-]clockwise$|clock[_-]counter[_-]clockwise|arrow_counter_clockwise|rotate.*left/i, bonus: -120 },
|
|
844
|
+
],
|
|
845
|
+
},
|
|
846
|
+
]);
|
|
824
847
|
|
|
825
|
-
const SLOT_PREFERENCE_RULES = Object.freeze({
|
|
826
|
-
lucide: [
|
|
827
|
-
{
|
|
828
|
-
slotPatterns: [/\b(add|new|create)\s+bookmark\b/i, /\bbookmark\s+(add|new|create)\b/i],
|
|
829
|
-
iconPreferences: [
|
|
830
|
-
{ pattern: /^bookmark-plus$/i, bonus: 500 },
|
|
831
|
-
{ pattern: /^bookmark$/i, bonus: 40 },
|
|
832
|
-
{ pattern: /waves-ladder|map-pin/i, bonus: -220 },
|
|
833
|
-
],
|
|
834
|
-
},
|
|
835
|
-
{
|
|
836
|
-
slotPatterns: [/users/i, /team/i],
|
|
837
|
-
iconPreferences: [
|
|
838
|
-
{ pattern: /^users$/i, bonus: 28 },
|
|
839
|
-
{ pattern: /^users-2$/i, bonus: 20 },
|
|
840
|
-
{ pattern: /^user-2$/i, bonus: -12 },
|
|
841
|
-
],
|
|
842
|
-
},
|
|
843
|
-
{
|
|
844
|
-
slotPatterns: [/database/i, /storage/i],
|
|
845
|
-
iconPreferences: [
|
|
846
|
-
{ pattern: /^database$/i, bonus: 48 },
|
|
847
|
-
{ pattern: /^database-(backup|search)$/i, bonus: 28 },
|
|
848
|
-
{ pattern: /^database-zap$/i, bonus: -34 },
|
|
849
|
-
],
|
|
850
|
-
},
|
|
851
|
-
{
|
|
852
|
-
slotPatterns: [/security/i, /privacy/i, /safe/i, /protection/i],
|
|
853
|
-
iconPreferences: [
|
|
854
|
-
{ pattern: /^shield$/i, bonus: 80 },
|
|
855
|
-
{ pattern: /^shield-check$/i, bonus: 76 },
|
|
856
|
-
{ pattern: /^lock$/i, bonus: 52 },
|
|
857
|
-
{ pattern: /^lock-keyhole$/i, bonus: 48 },
|
|
858
|
-
{ pattern: /open|unlock|ban|minus|off|slash/i, bonus: -80 },
|
|
859
|
-
],
|
|
860
|
-
},
|
|
861
|
-
],
|
|
862
|
-
mingcute: [
|
|
848
|
+
const SLOT_PREFERENCE_RULES = Object.freeze({
|
|
849
|
+
lucide: [
|
|
850
|
+
{
|
|
851
|
+
slotPatterns: [/\b(add|new|create)\s+bookmark\b/i, /\bbookmark\s+(add|new|create)\b/i],
|
|
852
|
+
iconPreferences: [
|
|
853
|
+
{ pattern: /^bookmark-plus$/i, bonus: 500 },
|
|
854
|
+
{ pattern: /^bookmark$/i, bonus: 40 },
|
|
855
|
+
{ pattern: /waves-ladder|map-pin/i, bonus: -220 },
|
|
856
|
+
],
|
|
857
|
+
},
|
|
863
858
|
{
|
|
864
|
-
slotPatterns: [/
|
|
865
|
-
iconPreferences: [
|
|
866
|
-
{ pattern: /^
|
|
867
|
-
{ pattern: /^
|
|
868
|
-
{ pattern: /^
|
|
869
|
-
|
|
870
|
-
|
|
859
|
+
slotPatterns: [/users/i, /team/i],
|
|
860
|
+
iconPreferences: [
|
|
861
|
+
{ pattern: /^users$/i, bonus: 28 },
|
|
862
|
+
{ pattern: /^users-2$/i, bonus: 20 },
|
|
863
|
+
{ pattern: /^user-2$/i, bonus: -12 },
|
|
864
|
+
],
|
|
865
|
+
},
|
|
866
|
+
{
|
|
867
|
+
slotPatterns: [/database/i, /storage/i],
|
|
868
|
+
iconPreferences: [
|
|
869
|
+
{ pattern: /^database$/i, bonus: 48 },
|
|
870
|
+
{ pattern: /^database-(backup|search)$/i, bonus: 28 },
|
|
871
|
+
{ pattern: /^database-zap$/i, bonus: -34 },
|
|
872
|
+
],
|
|
873
|
+
},
|
|
874
|
+
{
|
|
875
|
+
slotPatterns: [/security/i, /privacy/i, /safe/i, /protection/i],
|
|
876
|
+
iconPreferences: [
|
|
877
|
+
{ pattern: /^shield$/i, bonus: 80 },
|
|
878
|
+
{ pattern: /^shield-check$/i, bonus: 76 },
|
|
879
|
+
{ pattern: /^lock$/i, bonus: 52 },
|
|
880
|
+
{ pattern: /^lock-keyhole$/i, bonus: 48 },
|
|
881
|
+
{ pattern: /open|unlock|ban|minus|off|slash/i, bonus: -80 },
|
|
882
|
+
],
|
|
883
|
+
},
|
|
884
|
+
],
|
|
885
|
+
mingcute: [
|
|
886
|
+
{
|
|
887
|
+
slotPatterns: [/home/i],
|
|
888
|
+
iconPreferences: [
|
|
889
|
+
{ pattern: /^home_3_line$/i, bonus: 160 },
|
|
890
|
+
{ pattern: /^home_2_line$/i, bonus: 8 },
|
|
891
|
+
{ pattern: /^home_1_line$/i, bonus: 4 },
|
|
892
|
+
{ pattern: /^home_wifi_line$/i, bonus: -24 },
|
|
893
|
+
],
|
|
871
894
|
},
|
|
872
895
|
{
|
|
873
896
|
slotPatterns: [/create/i, /add/i, /plus/i, /compose/i],
|
|
@@ -877,95 +900,95 @@ const SLOT_PREFERENCE_RULES = Object.freeze({
|
|
|
877
900
|
{ pattern: /^add_circle_line$/i, bonus: 6 },
|
|
878
901
|
],
|
|
879
902
|
},
|
|
880
|
-
{
|
|
881
|
-
slotPatterns: [/alerts?/i, /notification/i],
|
|
882
|
-
iconPreferences: [
|
|
883
|
-
{ pattern: /^notification_line$/i, bonus: 36 },
|
|
884
|
-
{ pattern: /^notification_off_line$/i, bonus: -28 },
|
|
885
|
-
],
|
|
886
|
-
},
|
|
887
|
-
{
|
|
888
|
-
slotPatterns: [/profile/i, /user/i, /account/i],
|
|
889
|
-
iconPreferences: [
|
|
890
|
-
{ pattern: /^user_1_line$/i, bonus: 44 },
|
|
891
|
-
{ pattern: /^user_4_line$/i, bonus: -16 },
|
|
892
|
-
],
|
|
893
|
-
},
|
|
894
|
-
{
|
|
895
|
-
slotPatterns: [/search/i],
|
|
896
|
-
iconPreferences: [
|
|
897
|
-
{ pattern: /^search_line$/i, bonus: 70 },
|
|
898
|
-
{ pattern: /^search_[23]_line$/i, bonus: 18 },
|
|
899
|
-
{ pattern: /^search_.*_ai_line$/i, bonus: -70 },
|
|
900
|
-
],
|
|
901
|
-
},
|
|
902
|
-
{
|
|
903
|
-
slotPatterns: [/bookmark/i, /saved?/i],
|
|
904
|
-
iconPreferences: [
|
|
905
|
-
{ pattern: /^bookmark_line$/i, bonus: 34 },
|
|
906
|
-
{ pattern: /^bookmarks_line$/i, bonus: 28 },
|
|
907
|
-
{ pattern: /^bookmark_(add|edit|remove)_line$/i, bonus: -20 },
|
|
908
|
-
],
|
|
909
|
-
},
|
|
910
|
-
{
|
|
911
|
-
slotPatterns: [/trending/i, /popular/i, /top stories/i],
|
|
912
|
-
iconPreferences: [
|
|
913
|
-
{ pattern: /^trending_up_line$/i, bonus: 150 },
|
|
914
|
-
{ pattern: /^trending_down_line$/i, bonus: -30 },
|
|
915
|
-
],
|
|
916
|
-
},
|
|
917
|
-
{
|
|
918
|
-
slotPatterns: [/read more/i, /continue/i, /open article/i],
|
|
919
|
-
iconPreferences: [
|
|
920
|
-
{ pattern: /^arrow_right_line$/i, bonus: 72 },
|
|
921
|
-
{ pattern: /^arrow_to_right_line$/i, bonus: 40 },
|
|
922
|
-
{ pattern: /^align_arrow_right_line$/i, bonus: -30 },
|
|
923
|
-
],
|
|
924
|
-
},
|
|
925
|
-
{
|
|
926
|
-
slotPatterns: [/categor(?:y|ies)/i, /chips?/i, /filter/i, /topics?/i],
|
|
927
|
-
iconPreferences: [
|
|
928
|
-
{ pattern: /^filter_line$/i, bonus: 34 },
|
|
929
|
-
{ pattern: /^filter_[23]_line$/i, bonus: 22 },
|
|
930
|
-
{ pattern: /^tag_line$/i, bonus: 16 },
|
|
931
|
-
],
|
|
932
|
-
},
|
|
933
|
-
{
|
|
934
|
-
slotPatterns: [/news/i, /article/i, /headline/i, /logo/i, /title/i],
|
|
935
|
-
iconPreferences: [
|
|
936
|
-
{ pattern: /^news_line$/i, bonus: 76 },
|
|
937
|
-
{ pattern: /^news_2_line$/i, bonus: 46 },
|
|
938
|
-
{ pattern: /^appstore_line$/i, bonus: -44 },
|
|
939
|
-
{ pattern: /^apple_fruit_line$/i, bonus: -44 },
|
|
940
|
-
],
|
|
941
|
-
},
|
|
942
|
-
{
|
|
943
|
-
slotPatterns: [/projects?/i],
|
|
944
|
-
iconPreferences: [
|
|
945
|
-
{ pattern: /^folder_locked_line$/i, bonus: -70 },
|
|
946
|
-
],
|
|
947
|
-
},
|
|
948
|
-
],
|
|
949
|
-
});
|
|
950
|
-
|
|
951
|
-
function normalizeText(value) {
|
|
952
|
-
return String(value || '')
|
|
953
|
-
.toLowerCase()
|
|
903
|
+
{
|
|
904
|
+
slotPatterns: [/alerts?/i, /notification/i],
|
|
905
|
+
iconPreferences: [
|
|
906
|
+
{ pattern: /^notification_line$/i, bonus: 36 },
|
|
907
|
+
{ pattern: /^notification_off_line$/i, bonus: -28 },
|
|
908
|
+
],
|
|
909
|
+
},
|
|
910
|
+
{
|
|
911
|
+
slotPatterns: [/profile/i, /user/i, /account/i],
|
|
912
|
+
iconPreferences: [
|
|
913
|
+
{ pattern: /^user_1_line$/i, bonus: 44 },
|
|
914
|
+
{ pattern: /^user_4_line$/i, bonus: -16 },
|
|
915
|
+
],
|
|
916
|
+
},
|
|
917
|
+
{
|
|
918
|
+
slotPatterns: [/search/i],
|
|
919
|
+
iconPreferences: [
|
|
920
|
+
{ pattern: /^search_line$/i, bonus: 70 },
|
|
921
|
+
{ pattern: /^search_[23]_line$/i, bonus: 18 },
|
|
922
|
+
{ pattern: /^search_.*_ai_line$/i, bonus: -70 },
|
|
923
|
+
],
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
slotPatterns: [/bookmark/i, /saved?/i],
|
|
927
|
+
iconPreferences: [
|
|
928
|
+
{ pattern: /^bookmark_line$/i, bonus: 34 },
|
|
929
|
+
{ pattern: /^bookmarks_line$/i, bonus: 28 },
|
|
930
|
+
{ pattern: /^bookmark_(add|edit|remove)_line$/i, bonus: -20 },
|
|
931
|
+
],
|
|
932
|
+
},
|
|
933
|
+
{
|
|
934
|
+
slotPatterns: [/trending/i, /popular/i, /top stories/i],
|
|
935
|
+
iconPreferences: [
|
|
936
|
+
{ pattern: /^trending_up_line$/i, bonus: 150 },
|
|
937
|
+
{ pattern: /^trending_down_line$/i, bonus: -30 },
|
|
938
|
+
],
|
|
939
|
+
},
|
|
940
|
+
{
|
|
941
|
+
slotPatterns: [/read more/i, /continue/i, /open article/i],
|
|
942
|
+
iconPreferences: [
|
|
943
|
+
{ pattern: /^arrow_right_line$/i, bonus: 72 },
|
|
944
|
+
{ pattern: /^arrow_to_right_line$/i, bonus: 40 },
|
|
945
|
+
{ pattern: /^align_arrow_right_line$/i, bonus: -30 },
|
|
946
|
+
],
|
|
947
|
+
},
|
|
948
|
+
{
|
|
949
|
+
slotPatterns: [/categor(?:y|ies)/i, /chips?/i, /filter/i, /topics?/i],
|
|
950
|
+
iconPreferences: [
|
|
951
|
+
{ pattern: /^filter_line$/i, bonus: 34 },
|
|
952
|
+
{ pattern: /^filter_[23]_line$/i, bonus: 22 },
|
|
953
|
+
{ pattern: /^tag_line$/i, bonus: 16 },
|
|
954
|
+
],
|
|
955
|
+
},
|
|
956
|
+
{
|
|
957
|
+
slotPatterns: [/news/i, /article/i, /headline/i, /logo/i, /title/i],
|
|
958
|
+
iconPreferences: [
|
|
959
|
+
{ pattern: /^news_line$/i, bonus: 76 },
|
|
960
|
+
{ pattern: /^news_2_line$/i, bonus: 46 },
|
|
961
|
+
{ pattern: /^appstore_line$/i, bonus: -44 },
|
|
962
|
+
{ pattern: /^apple_fruit_line$/i, bonus: -44 },
|
|
963
|
+
],
|
|
964
|
+
},
|
|
965
|
+
{
|
|
966
|
+
slotPatterns: [/projects?/i],
|
|
967
|
+
iconPreferences: [
|
|
968
|
+
{ pattern: /^folder_locked_line$/i, bonus: -70 },
|
|
969
|
+
],
|
|
970
|
+
},
|
|
971
|
+
],
|
|
972
|
+
});
|
|
973
|
+
|
|
974
|
+
function normalizeText(value) {
|
|
975
|
+
return String(value || '')
|
|
976
|
+
.toLowerCase()
|
|
954
977
|
.replace(/[_:]+/g, ' ')
|
|
955
978
|
.replace(/[^a-z0-9\s-]/g, ' ')
|
|
956
979
|
.replace(/-/g, ' ')
|
|
957
980
|
.replace(/\s+/g, ' ')
|
|
958
|
-
.trim();
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
function normalizeToken(token) {
|
|
962
|
-
const value = String(token || '').toLowerCase();
|
|
963
|
-
if (value.length > 4 && value.endsWith('ies')) return `${value.slice(0, -3)}y`;
|
|
964
|
-
if (value.length > 3 && value.endsWith('es')) return value.slice(0, -2);
|
|
965
|
-
if (value.length > 3 && value.endsWith('s')) return value.slice(0, -1);
|
|
966
|
-
return value;
|
|
967
|
-
}
|
|
968
|
-
|
|
981
|
+
.trim();
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
function normalizeToken(token) {
|
|
985
|
+
const value = String(token || '').toLowerCase();
|
|
986
|
+
if (value.length > 4 && value.endsWith('ies')) return `${value.slice(0, -3)}y`;
|
|
987
|
+
if (value.length > 3 && value.endsWith('es')) return value.slice(0, -2);
|
|
988
|
+
if (value.length > 3 && value.endsWith('s')) return value.slice(0, -1);
|
|
989
|
+
return value;
|
|
990
|
+
}
|
|
991
|
+
|
|
969
992
|
function tokenizeText(value) {
|
|
970
993
|
const normalized = normalizeText(value);
|
|
971
994
|
if (!normalized) return [];
|
|
@@ -977,235 +1000,337 @@ function dedupe(values) {
|
|
|
977
1000
|
return [...new Set(values.filter(Boolean))];
|
|
978
1001
|
}
|
|
979
1002
|
|
|
980
|
-
function
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
.
|
|
984
|
-
.flatMap((rule) => rule.terms);
|
|
1003
|
+
function stripBrandLogoWords(value) {
|
|
1004
|
+
return tokenizeText(value)
|
|
1005
|
+
.filter((token) => !BRAND_LOGO_WORDS.has(token))
|
|
1006
|
+
.join(' ');
|
|
985
1007
|
}
|
|
986
1008
|
|
|
987
|
-
function
|
|
988
|
-
return
|
|
1009
|
+
function hasSpecificBrandTerms(value) {
|
|
1010
|
+
return tokenizeText(stripBrandLogoWords(value))
|
|
1011
|
+
.some((token) => !BRAND_LOGO_GENERIC_WORDS.has(token));
|
|
989
1012
|
}
|
|
990
1013
|
|
|
991
|
-
function
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
const
|
|
995
|
-
return
|
|
1014
|
+
function isBrandLogoRecommendation(task, slot, library) {
|
|
1015
|
+
if (library === 'si') return true;
|
|
1016
|
+
const text = normalizeText(`${slot} ${task}`);
|
|
1017
|
+
const namesLogoOrBrand = /\b(logos?|brands?|wordmark|mark)\b/.test(text);
|
|
1018
|
+
return namesLogoOrBrand && hasSpecificBrandTerms(slot);
|
|
996
1019
|
}
|
|
997
1020
|
|
|
998
|
-
function
|
|
999
|
-
|
|
1000
|
-
return tokenizeText(icon.id).some((token) => (
|
|
1001
|
-
VARIANT_TOKENS.has(normalizeToken(token)) &&
|
|
1002
|
-
isVariantTokenRequested(token, requestedTerms)
|
|
1003
|
-
));
|
|
1004
|
-
}
|
|
1021
|
+
function buildBrandLogoQueryVariants(task, slot, library) {
|
|
1022
|
+
if (!isBrandLogoRecommendation(task, slot, library)) return [];
|
|
1005
1023
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
const
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
});
|
|
1012
|
-
const variants = expanded.matched.length > 0 ? expanded.variants.slice(1) : [];
|
|
1013
|
-
const normalizedValue = normalizeCjkSearchText(value);
|
|
1014
|
-
const containedMatches = [];
|
|
1024
|
+
const rawSlot = String(slot || '').trim();
|
|
1025
|
+
const normalizedSlot = normalizeText(slot);
|
|
1026
|
+
const strippedSlot = stripBrandLogoWords(slot);
|
|
1027
|
+
const usefulTokens = tokenizeText(strippedSlot)
|
|
1028
|
+
.filter((token) => !BRAND_LOGO_GENERIC_WORDS.has(token));
|
|
1015
1029
|
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
.filter(Boolean);
|
|
1023
|
-
const isContainedMatch = recordValues.some((term) => (
|
|
1024
|
-
term.length >= 2
|
|
1025
|
-
&& (normalizedValue.includes(term) || term.includes(normalizedValue))
|
|
1026
|
-
));
|
|
1027
|
-
if (!isContainedMatch) continue;
|
|
1028
|
-
|
|
1029
|
-
const firstIndex = Math.min(
|
|
1030
|
-
...recordValues
|
|
1031
|
-
.map((term) => normalizedValue.indexOf(term))
|
|
1032
|
-
.filter((index) => index >= 0)
|
|
1033
|
-
);
|
|
1034
|
-
containedMatches.push({
|
|
1035
|
-
index: Number.isFinite(firstIndex) ? firstIndex : Number.MAX_SAFE_INTEGER,
|
|
1036
|
-
concepts: record.maps_to || [],
|
|
1037
|
-
});
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
containedMatches
|
|
1042
|
-
.sort((left, right) => left.index - right.index)
|
|
1043
|
-
.forEach((match) => {
|
|
1044
|
-
for (const concept of match.concepts) {
|
|
1045
|
-
const normalizedConcept = normalizeCjkSearchText(concept);
|
|
1046
|
-
if (normalizedConcept) variants.push(normalizedConcept);
|
|
1047
|
-
}
|
|
1048
|
-
});
|
|
1049
|
-
|
|
1050
|
-
return dedupe(variants);
|
|
1030
|
+
return dedupe([
|
|
1031
|
+
rawSlot,
|
|
1032
|
+
normalizedSlot,
|
|
1033
|
+
strippedSlot,
|
|
1034
|
+
...usefulTokens,
|
|
1035
|
+
]);
|
|
1051
1036
|
}
|
|
1052
1037
|
|
|
1053
|
-
function
|
|
1054
|
-
const
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1038
|
+
function buildDirectLocalizedIntentTerms(value) {
|
|
1039
|
+
const text = String(value || '');
|
|
1040
|
+
return DIRECT_LOCALIZED_INTENT_RULES
|
|
1041
|
+
.filter((rule) => rule.pattern.test(text))
|
|
1042
|
+
.flatMap((rule) => rule.terms);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
function buildRequestedTermSet(intentTerms = []) {
|
|
1046
|
+
return new Set(intentTerms.map(normalizeToken).filter(Boolean));
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
function isVariantTokenRequested(token, requestedTerms) {
|
|
1050
|
+
const normalizedToken = normalizeToken(token);
|
|
1051
|
+
if (requestedTerms.has(normalizedToken)) return true;
|
|
1052
|
+
const aliases = REQUESTED_VARIANT_ALIASES[normalizedToken] || [];
|
|
1053
|
+
return aliases.some((alias) => requestedTerms.has(normalizeToken(alias)));
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
function isIconVariantExplicitlyRequested(icon, intentTerms = []) {
|
|
1057
|
+
const requestedTerms = buildRequestedTermSet(intentTerms);
|
|
1058
|
+
return tokenizeText(icon.id).some((token) => (
|
|
1059
|
+
VARIANT_TOKENS.has(normalizeToken(token)) &&
|
|
1060
|
+
isVariantTokenRequested(token, requestedTerms)
|
|
1061
|
+
));
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
function buildLocalizedVariants(value, locale) {
|
|
1065
|
+
if (!locale) return [];
|
|
1066
|
+
const expanded = expandCjkQuery(value, {
|
|
1067
|
+
locale,
|
|
1068
|
+
terms: multilingualExpansionTerms,
|
|
1069
|
+
});
|
|
1070
|
+
const variants = expanded.matched.length > 0 ? expanded.variants.slice(1) : [];
|
|
1071
|
+
const normalizedValue = normalizeCjkSearchText(value);
|
|
1072
|
+
const containedMatches = [];
|
|
1073
|
+
|
|
1074
|
+
if (normalizedValue) {
|
|
1075
|
+
for (const record of multilingualExpansionTerms) {
|
|
1076
|
+
if (record.locale !== locale || record.gate !== 'auto_accept') continue;
|
|
1077
|
+
|
|
1078
|
+
const recordValues = [record.term, ...(record.variants || [])]
|
|
1079
|
+
.map((term) => normalizeCjkSearchText(term))
|
|
1080
|
+
.filter(Boolean);
|
|
1081
|
+
const isContainedMatch = recordValues.some((term) => (
|
|
1082
|
+
term.length >= 2
|
|
1083
|
+
&& (normalizedValue.includes(term) || term.includes(normalizedValue))
|
|
1084
|
+
));
|
|
1085
|
+
if (!isContainedMatch) continue;
|
|
1086
|
+
|
|
1087
|
+
const firstIndex = Math.min(
|
|
1088
|
+
...recordValues
|
|
1089
|
+
.map((term) => normalizedValue.indexOf(term))
|
|
1090
|
+
.filter((index) => index >= 0)
|
|
1091
|
+
);
|
|
1092
|
+
containedMatches.push({
|
|
1093
|
+
index: Number.isFinite(firstIndex) ? firstIndex : Number.MAX_SAFE_INTEGER,
|
|
1094
|
+
concepts: record.maps_to || [],
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
containedMatches
|
|
1100
|
+
.sort((left, right) => left.index - right.index)
|
|
1101
|
+
.forEach((match) => {
|
|
1102
|
+
for (const concept of match.concepts) {
|
|
1103
|
+
const normalizedConcept = normalizeCjkSearchText(concept);
|
|
1104
|
+
if (normalizedConcept) variants.push(normalizedConcept);
|
|
1105
|
+
}
|
|
1106
|
+
});
|
|
1107
|
+
|
|
1108
|
+
return dedupe(variants);
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
function buildSlotIntentTerms(task, slot, locale = null) {
|
|
1112
|
+
const taskTokens = tokenizeText(task);
|
|
1113
|
+
const slotTokens = tokenizeText(slot);
|
|
1114
|
+
const usefulSlotTokens = slotTokens.filter((token) => !GENERIC_SLOT_WORDS.has(token));
|
|
1115
|
+
const localizedSlotTokens = buildLocalizedVariants(slot, locale).flatMap(tokenizeText);
|
|
1116
|
+
const localizedTaskTokens = buildLocalizedVariants(task, locale).flatMap(tokenizeText);
|
|
1117
|
+
const directSlotTokens = buildDirectLocalizedIntentTerms(slot);
|
|
1118
|
+
|
|
1119
|
+
const expanded = [...usefulSlotTokens];
|
|
1120
|
+
|
|
1121
|
+
const usefulTaskTokens = taskTokens.filter((token) => !GENERIC_SLOT_WORDS.has(token));
|
|
1122
|
+
expanded.push(...usefulTaskTokens);
|
|
1123
|
+
expanded.push(...localizedSlotTokens);
|
|
1124
|
+
expanded.push(...localizedTaskTokens);
|
|
1125
|
+
expanded.push(...directSlotTokens);
|
|
1126
|
+
|
|
1127
|
+
const variants = buildIntentQueryVariants(`${slot} ${task}`, {
|
|
1128
|
+
baseQuery: slot,
|
|
1129
|
+
maxVariants: 8,
|
|
1072
1130
|
});
|
|
1073
1131
|
for (const variant of variants) {
|
|
1074
1132
|
expanded.push(...tokenizeText(variant));
|
|
1075
1133
|
}
|
|
1076
1134
|
|
|
1077
|
-
const slotRuleTerms = dedupe([...usefulSlotTokens, ...localizedSlotTokens, ...directSlotTokens]);
|
|
1078
|
-
for (const rule of getMatchingSlotRules(slot, slotRuleTerms)) {
|
|
1079
|
-
for (const variant of rule.queryVariants || []) {
|
|
1080
|
-
expanded.push(...tokenizeText(variant));
|
|
1081
|
-
}
|
|
1135
|
+
const slotRuleTerms = dedupe([...usefulSlotTokens, ...localizedSlotTokens, ...directSlotTokens]);
|
|
1136
|
+
for (const rule of getMatchingSlotRules(slot, slotRuleTerms)) {
|
|
1137
|
+
for (const variant of rule.queryVariants || []) {
|
|
1138
|
+
expanded.push(...tokenizeText(variant));
|
|
1139
|
+
}
|
|
1082
1140
|
}
|
|
1083
1141
|
|
|
1084
|
-
return dedupe(expanded);
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1087
|
-
function buildSlotQueryVariants(task, slot, locale = null) {
|
|
1088
|
-
const localizedSlotVariants = buildLocalizedVariants(slot, locale);
|
|
1089
|
-
const localizedVariants = [
|
|
1090
|
-
...localizedSlotVariants,
|
|
1091
|
-
...buildLocalizedVariants(`${slot} ${task}`, locale),
|
|
1092
|
-
];
|
|
1093
|
-
const variants = buildIntentQueryVariants(`${slot} ${task}`, {
|
|
1094
|
-
baseQuery: slot,
|
|
1095
|
-
maxVariants: 8,
|
|
1096
|
-
});
|
|
1097
|
-
variants.unshift(...localizedVariants);
|
|
1098
|
-
const usefulSlotTokens = tokenizeText(slot).filter((token) => !GENERIC_SLOT_WORDS.has(token));
|
|
1099
|
-
variants.push(...usefulSlotTokens);
|
|
1100
|
-
const slotRuleTerms = [
|
|
1101
|
-
...tokenizeText(`${slot} ${localizedSlotVariants.join(' ')}`),
|
|
1102
|
-
...buildDirectLocalizedIntentTerms(slot),
|
|
1103
|
-
]
|
|
1104
|
-
.filter((token) => !GENERIC_SLOT_WORDS.has(token));
|
|
1105
|
-
const ruleVariants = getMatchingSlotRules(slot, slotRuleTerms)
|
|
1106
|
-
.flatMap((rule) => rule.queryVariants || []);
|
|
1107
|
-
variants.unshift(...ruleVariants);
|
|
1108
|
-
return dedupe(variants).slice(0, 12);
|
|
1109
|
-
}
|
|
1142
|
+
return dedupe(expanded);
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
function buildSlotQueryVariants(task, slot, locale = null) {
|
|
1146
|
+
const localizedSlotVariants = buildLocalizedVariants(slot, locale);
|
|
1147
|
+
const localizedVariants = [
|
|
1148
|
+
...localizedSlotVariants,
|
|
1149
|
+
...buildLocalizedVariants(`${slot} ${task}`, locale),
|
|
1150
|
+
];
|
|
1151
|
+
const variants = buildIntentQueryVariants(`${slot} ${task}`, {
|
|
1152
|
+
baseQuery: slot,
|
|
1153
|
+
maxVariants: 8,
|
|
1154
|
+
});
|
|
1155
|
+
variants.unshift(...localizedVariants);
|
|
1156
|
+
const usefulSlotTokens = tokenizeText(slot).filter((token) => !GENERIC_SLOT_WORDS.has(token));
|
|
1157
|
+
variants.push(...usefulSlotTokens);
|
|
1158
|
+
const slotRuleTerms = [
|
|
1159
|
+
...tokenizeText(`${slot} ${localizedSlotVariants.join(' ')}`),
|
|
1160
|
+
...buildDirectLocalizedIntentTerms(slot),
|
|
1161
|
+
]
|
|
1162
|
+
.filter((token) => !GENERIC_SLOT_WORDS.has(token));
|
|
1163
|
+
const ruleVariants = getMatchingSlotRules(slot, slotRuleTerms)
|
|
1164
|
+
.flatMap((rule) => rule.queryVariants || []);
|
|
1165
|
+
variants.unshift(...ruleVariants);
|
|
1166
|
+
return dedupe(variants).slice(0, 12);
|
|
1167
|
+
}
|
|
1110
1168
|
|
|
1111
1169
|
function scoreLexicalFit(icon, intentTerms, slotLabel, taskLabel = '') {
|
|
1112
|
-
const tokens = new Set([
|
|
1113
|
-
...tokenizeText(icon.id),
|
|
1114
|
-
...tokenizeText(icon.name),
|
|
1115
|
-
...tokenizeText(`${icon.lib}:${icon.id}`),
|
|
1116
|
-
]);
|
|
1117
|
-
const normalizedId = normalizeText(icon.id);
|
|
1118
|
-
const normalizedName = normalizeText(icon.name);
|
|
1119
|
-
const normalizedSlot = normalizeText(slotLabel);
|
|
1120
|
-
const slotTerms = tokenizeText(slotLabel).filter((token) => !GENERIC_SLOT_WORDS.has(token));
|
|
1121
|
-
const taskTerms = tokenizeText(taskLabel).filter((token) => !GENERIC_SLOT_WORDS.has(token));
|
|
1170
|
+
const tokens = new Set([
|
|
1171
|
+
...tokenizeText(icon.id),
|
|
1172
|
+
...tokenizeText(icon.name),
|
|
1173
|
+
...tokenizeText(`${icon.lib}:${icon.id}`),
|
|
1174
|
+
]);
|
|
1175
|
+
const normalizedId = normalizeText(icon.id);
|
|
1176
|
+
const normalizedName = normalizeText(icon.name);
|
|
1177
|
+
const normalizedSlot = normalizeText(slotLabel);
|
|
1178
|
+
const slotTerms = tokenizeText(slotLabel).filter((token) => !GENERIC_SLOT_WORDS.has(token));
|
|
1179
|
+
const taskTerms = tokenizeText(taskLabel).filter((token) => !GENERIC_SLOT_WORDS.has(token));
|
|
1180
|
+
|
|
1181
|
+
let score = 0;
|
|
1182
|
+
for (const term of slotTerms) {
|
|
1183
|
+
if (tokens.has(term)) score += 22;
|
|
1184
|
+
else if (normalizedId.includes(term) || normalizedName.includes(term)) score += 14;
|
|
1185
|
+
|
|
1186
|
+
if (normalizedId === term || normalizedName === term) {
|
|
1187
|
+
score += 24;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
for (const term of intentTerms) {
|
|
1192
|
+
if (tokens.has(term)) score += 12;
|
|
1193
|
+
else if (normalizedId.includes(term) || normalizedName.includes(term)) score += 7;
|
|
1194
|
+
|
|
1195
|
+
if (normalizedId === term || normalizedName === term) {
|
|
1196
|
+
score += 14;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
for (const term of taskTerms) {
|
|
1201
|
+
if (tokens.has(term)) score += 3;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
if (normalizedSlot && (normalizedId === normalizedSlot || normalizedName === normalizedSlot)) {
|
|
1205
|
+
score += 26;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
return score;
|
|
1209
|
+
}
|
|
1122
1210
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1211
|
+
function collectBrandCandidateTexts(icon, semanticRecord) {
|
|
1212
|
+
const semanticValues = semanticRecord ? [
|
|
1213
|
+
semanticRecord.label,
|
|
1214
|
+
semanticRecord.source_name,
|
|
1215
|
+
semanticRecord.slug,
|
|
1216
|
+
semanticRecord.name,
|
|
1217
|
+
semanticRecord.meaning,
|
|
1218
|
+
semanticRecord.purpose,
|
|
1219
|
+
...(semanticRecord.aliases || []),
|
|
1220
|
+
...(semanticRecord.synonyms || []),
|
|
1221
|
+
...(semanticRecord.search_terms || []),
|
|
1222
|
+
...(semanticRecord.semantic_tags || []),
|
|
1223
|
+
] : [];
|
|
1127
1224
|
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1225
|
+
return dedupe([
|
|
1226
|
+
icon.id,
|
|
1227
|
+
icon.name,
|
|
1228
|
+
`${icon.lib}:${icon.id}`,
|
|
1229
|
+
...(icon.aliases || []),
|
|
1230
|
+
...(icon.synonyms || []),
|
|
1231
|
+
...(icon.searchTerms || []),
|
|
1232
|
+
...(icon.semanticTags || []),
|
|
1233
|
+
...(icon.semantic?.aliases || []),
|
|
1234
|
+
...(icon.semantic?.synonyms || []),
|
|
1235
|
+
...(icon.semantic?.search_terms || []),
|
|
1236
|
+
...(icon.semantic?.semantic_tags || []),
|
|
1237
|
+
...semanticValues,
|
|
1238
|
+
].map((value) => normalizeText(value)).filter(Boolean));
|
|
1239
|
+
}
|
|
1132
1240
|
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
else if (normalizedId.includes(term) || normalizedName.includes(term)) score += 7;
|
|
1241
|
+
function getBrandLogoMatchBonus(icon, semanticRecord, slotLabel, taskLabel, library) {
|
|
1242
|
+
if (!isBrandLogoRecommendation(taskLabel, slotLabel, library)) return 0;
|
|
1136
1243
|
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1244
|
+
const slotCandidates = buildBrandLogoQueryVariants(taskLabel, slotLabel, library)
|
|
1245
|
+
.map((value) => normalizeText(value))
|
|
1246
|
+
.filter((value) => value.length >= 2);
|
|
1247
|
+
const iconCandidates = collectBrandCandidateTexts(icon, semanticRecord);
|
|
1248
|
+
const iconTokens = new Set(iconCandidates.flatMap(tokenizeText));
|
|
1249
|
+
const meaningfulSlotTokens = dedupe(
|
|
1250
|
+
slotCandidates
|
|
1251
|
+
.flatMap(tokenizeText)
|
|
1252
|
+
.filter((token) => !BRAND_LOGO_GENERIC_WORDS.has(token))
|
|
1253
|
+
);
|
|
1141
1254
|
|
|
1142
|
-
|
|
1143
|
-
|
|
1255
|
+
let best = 0;
|
|
1256
|
+
for (const slotCandidate of slotCandidates) {
|
|
1257
|
+
for (const iconCandidate of iconCandidates) {
|
|
1258
|
+
if (slotCandidate === iconCandidate) {
|
|
1259
|
+
best = Math.max(best, 360);
|
|
1260
|
+
} else if (slotCandidate.length >= 3 && iconCandidate.includes(slotCandidate)) {
|
|
1261
|
+
best = Math.max(best, 260);
|
|
1262
|
+
} else if (iconCandidate.length >= 3 && slotCandidate.includes(iconCandidate)) {
|
|
1263
|
+
best = Math.max(best, 180);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1144
1266
|
}
|
|
1145
1267
|
|
|
1146
|
-
|
|
1147
|
-
|
|
1268
|
+
const overlapCount = meaningfulSlotTokens.filter((token) => iconTokens.has(token)).length;
|
|
1269
|
+
if (meaningfulSlotTokens.length > 0 && overlapCount === meaningfulSlotTokens.length) {
|
|
1270
|
+
best = Math.max(best, 220 + overlapCount * 20);
|
|
1271
|
+
} else {
|
|
1272
|
+
best = Math.max(best, overlapCount * 30);
|
|
1148
1273
|
}
|
|
1149
1274
|
|
|
1150
|
-
return
|
|
1275
|
+
return best;
|
|
1151
1276
|
}
|
|
1152
1277
|
|
|
1153
1278
|
function getVariantPenalty(icon, intentTerms = []) {
|
|
1154
|
-
const normalizedId = normalizeText(icon.id);
|
|
1155
|
-
const requestedTerms = buildRequestedTermSet(intentTerms);
|
|
1156
|
-
let penalty = 0;
|
|
1157
|
-
for (const rule of VARIANT_PENALTIES) {
|
|
1158
|
-
if (!rule.pattern.test(normalizedId)) continue;
|
|
1159
|
-
if (isVariantTokenRequested(rule.token, requestedTerms)) continue;
|
|
1160
|
-
penalty += rule.penalty;
|
|
1161
|
-
}
|
|
1162
|
-
return penalty;
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
function getBrandPenalty(icon, intentTerms = []) {
|
|
1166
|
-
const requestedTerms = buildRequestedTermSet(intentTerms);
|
|
1167
|
-
if (isVariantTokenRequested('brand', requestedTerms)) return 0;
|
|
1168
|
-
return icon.lib === 'simpleicons' ? 80 : 0;
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
|
-
function getMatchingSlotRules(slotLabel, intentTerms = []) {
|
|
1172
|
-
const rawSlotText = String(slotLabel || '');
|
|
1173
|
-
const slotText = normalizeText(slotLabel);
|
|
1174
|
-
const intentText = normalizeText(intentTerms.join(' '));
|
|
1175
|
-
return COMMON_SLOT_PREFERENCE_RULES
|
|
1176
|
-
.filter((rule) => rule.slotPatterns.some((pattern) => (
|
|
1177
|
-
pattern.test(slotText) ||
|
|
1178
|
-
pattern.test(rawSlotText) ||
|
|
1179
|
-
pattern.test(intentText)
|
|
1180
|
-
)))
|
|
1181
|
-
.sort((left, right) => (right.priority || 0) - (left.priority || 0));
|
|
1182
|
-
}
|
|
1279
|
+
const normalizedId = normalizeText(icon.id);
|
|
1280
|
+
const requestedTerms = buildRequestedTermSet(intentTerms);
|
|
1281
|
+
let penalty = 0;
|
|
1282
|
+
for (const rule of VARIANT_PENALTIES) {
|
|
1283
|
+
if (!rule.pattern.test(normalizedId)) continue;
|
|
1284
|
+
if (isVariantTokenRequested(rule.token, requestedTerms)) continue;
|
|
1285
|
+
penalty += rule.penalty;
|
|
1286
|
+
}
|
|
1287
|
+
return penalty;
|
|
1288
|
+
}
|
|
1183
1289
|
|
|
1184
|
-
function
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1290
|
+
function getBrandPenalty(icon, intentTerms = []) {
|
|
1291
|
+
const requestedTerms = buildRequestedTermSet(intentTerms);
|
|
1292
|
+
if (isVariantTokenRequested('brand', requestedTerms)) return 0;
|
|
1293
|
+
return icon.lib === 'simpleicons' ? 80 : 0;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
function getMatchingSlotRules(slotLabel, intentTerms = []) {
|
|
1297
|
+
const rawSlotText = String(slotLabel || '');
|
|
1298
|
+
const slotText = normalizeText(slotLabel);
|
|
1299
|
+
const intentText = normalizeText(intentTerms.join(' '));
|
|
1300
|
+
return COMMON_SLOT_PREFERENCE_RULES
|
|
1301
|
+
.filter((rule) => rule.slotPatterns.some((pattern) => (
|
|
1302
|
+
pattern.test(slotText) ||
|
|
1303
|
+
pattern.test(rawSlotText) ||
|
|
1304
|
+
pattern.test(intentText)
|
|
1305
|
+
)))
|
|
1306
|
+
.sort((left, right) => (right.priority || 0) - (left.priority || 0));
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
function scoreSlotPreferenceRules(icon, rules = [], intentTerms = []) {
|
|
1310
|
+
let bonus = 0;
|
|
1311
|
+
const explicitlyRequestedVariant = isIconVariantExplicitlyRequested(icon, intentTerms);
|
|
1312
|
+
|
|
1313
|
+
for (const rule of rules) {
|
|
1314
|
+
for (const preference of rule.iconPreferences) {
|
|
1315
|
+
if (preference.pattern.test(icon.id)) {
|
|
1316
|
+
if (preference.bonus < 0 && explicitlyRequestedVariant) continue;
|
|
1317
|
+
bonus += preference.bonus;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1195
1320
|
}
|
|
1196
1321
|
|
|
1197
1322
|
return bonus;
|
|
1198
1323
|
}
|
|
1199
1324
|
|
|
1200
|
-
function getSlotPreferenceBonus(icon, slotLabel, intentTerms, library, requestedVariantTerms = intentTerms) {
|
|
1201
|
-
const slotText = `${slotLabel} ${requestedVariantTerms.join(' ')}`;
|
|
1202
|
-
const commonRules = getMatchingSlotRules(slotLabel, requestedVariantTerms);
|
|
1203
|
-
const libraryRules = (SLOT_PREFERENCE_RULES[library] || [])
|
|
1204
|
-
.filter((rule) => rule.slotPatterns.some((pattern) => pattern.test(slotText)));
|
|
1205
|
-
|
|
1206
|
-
return scoreSlotPreferenceRules(icon, commonRules, requestedVariantTerms) +
|
|
1207
|
-
scoreSlotPreferenceRules(icon, libraryRules, requestedVariantTerms);
|
|
1208
|
-
}
|
|
1325
|
+
function getSlotPreferenceBonus(icon, slotLabel, intentTerms, library, requestedVariantTerms = intentTerms) {
|
|
1326
|
+
const slotText = `${slotLabel} ${requestedVariantTerms.join(' ')}`;
|
|
1327
|
+
const commonRules = getMatchingSlotRules(slotLabel, requestedVariantTerms);
|
|
1328
|
+
const libraryRules = (SLOT_PREFERENCE_RULES[library] || [])
|
|
1329
|
+
.filter((rule) => rule.slotPatterns.some((pattern) => pattern.test(slotText)));
|
|
1330
|
+
|
|
1331
|
+
return scoreSlotPreferenceRules(icon, commonRules, requestedVariantTerms) +
|
|
1332
|
+
scoreSlotPreferenceRules(icon, libraryRules, requestedVariantTerms);
|
|
1333
|
+
}
|
|
1209
1334
|
|
|
1210
1335
|
function summarizeSemanticFit(slotLabel, semanticRecord, intentTerms) {
|
|
1211
1336
|
if (semanticRecord?.depicts && semanticRecord?.use_when) {
|
|
@@ -1223,7 +1348,7 @@ function summarizeSemanticFit(slotLabel, semanticRecord, intentTerms) {
|
|
|
1223
1348
|
return `Best available match for ${slotLabel}.`;
|
|
1224
1349
|
}
|
|
1225
1350
|
|
|
1226
|
-
function buildWhySelected(slotLabel, semanticRecord, iconResult) {
|
|
1351
|
+
function buildWhySelected(slotLabel, semanticRecord, iconResult) {
|
|
1227
1352
|
const label = semanticRecord?.label || iconResult.name;
|
|
1228
1353
|
if (semanticRecord?.depicts) {
|
|
1229
1354
|
return `${label} matches ${slotLabel} and visually reads as ${String(semanticRecord.depicts).toLowerCase()}.`;
|
|
@@ -1231,43 +1356,43 @@ function buildWhySelected(slotLabel, semanticRecord, iconResult) {
|
|
|
1231
1356
|
if (semanticRecord?.use_when) {
|
|
1232
1357
|
return `${label} matches ${slotLabel}. ${semanticRecord.use_when}`;
|
|
1233
1358
|
}
|
|
1234
|
-
return `${label} is the clearest match for ${slotLabel} from the current library.`;
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
function buildCandidatePayload(
|
|
1238
|
-
slotLabel,
|
|
1239
|
-
iconResult,
|
|
1240
|
-
semanticRecord,
|
|
1241
|
-
intentTerms,
|
|
1242
|
-
responseMode = 'plan',
|
|
1243
|
-
includeSvg = false,
|
|
1244
|
-
includeReason = true
|
|
1245
|
-
) {
|
|
1246
|
-
const payload = {
|
|
1247
|
-
id: iconResult.id,
|
|
1248
|
-
library: iconResult.library,
|
|
1249
|
-
name: iconResult.name,
|
|
1250
|
-
style: iconResult.style || 'outline',
|
|
1251
|
-
label: semanticRecord?.label || iconResult.semantic?.label || iconResult.name,
|
|
1252
|
-
};
|
|
1253
|
-
|
|
1254
|
-
if (includeReason) {
|
|
1255
|
-
payload.semantic_fit = summarizeSemanticFit(slotLabel, semanticRecord, intentTerms);
|
|
1256
|
-
payload.why_selected = buildWhySelected(slotLabel, semanticRecord, iconResult);
|
|
1257
|
-
}
|
|
1258
|
-
|
|
1259
|
-
if (includeSvg) {
|
|
1260
|
-
payload.svg = iconResult.svg;
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
if (responseMode === 'full') {
|
|
1264
|
-
payload.semantic = buildPublicSemanticPayload(semanticRecord) || iconResult.semantic || null;
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
return payload;
|
|
1268
|
-
}
|
|
1359
|
+
return `${label} is the clearest match for ${slotLabel} from the current library.`;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
function buildCandidatePayload(
|
|
1363
|
+
slotLabel,
|
|
1364
|
+
iconResult,
|
|
1365
|
+
semanticRecord,
|
|
1366
|
+
intentTerms,
|
|
1367
|
+
responseMode = 'plan',
|
|
1368
|
+
includeSvg = false,
|
|
1369
|
+
includeReason = true
|
|
1370
|
+
) {
|
|
1371
|
+
const payload = {
|
|
1372
|
+
id: iconResult.id,
|
|
1373
|
+
library: iconResult.library,
|
|
1374
|
+
name: iconResult.name,
|
|
1375
|
+
style: iconResult.style || 'outline',
|
|
1376
|
+
label: semanticRecord?.label || iconResult.semantic?.label || iconResult.name,
|
|
1377
|
+
};
|
|
1378
|
+
|
|
1379
|
+
if (includeReason) {
|
|
1380
|
+
payload.semantic_fit = summarizeSemanticFit(slotLabel, semanticRecord, intentTerms);
|
|
1381
|
+
payload.why_selected = buildWhySelected(slotLabel, semanticRecord, iconResult);
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
if (includeSvg) {
|
|
1385
|
+
payload.svg = iconResult.svg;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
if (responseMode === 'full') {
|
|
1389
|
+
payload.semantic = buildPublicSemanticPayload(semanticRecord) || iconResult.semantic || null;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
return payload;
|
|
1393
|
+
}
|
|
1269
1394
|
|
|
1270
|
-
async function mapWithConcurrency(items, limit, mapper) {
|
|
1395
|
+
async function mapWithConcurrency(items, limit, mapper) {
|
|
1271
1396
|
const results = new Array(items.length);
|
|
1272
1397
|
let nextIndex = 0;
|
|
1273
1398
|
|
|
@@ -1280,70 +1405,73 @@ async function mapWithConcurrency(items, limit, mapper) {
|
|
|
1280
1405
|
}
|
|
1281
1406
|
|
|
1282
1407
|
const workerCount = Math.min(Math.max(1, limit), items.length);
|
|
1283
|
-
await Promise.all(Array.from({ length: workerCount }, () => worker()));
|
|
1284
|
-
return results;
|
|
1285
|
-
}
|
|
1286
|
-
|
|
1287
|
-
function getConfidence(topScore, nextScore = 0) {
|
|
1288
|
-
if (topScore >= 90 && topScore - nextScore >= 20) {
|
|
1289
|
-
return { level: 'high', score: topScore };
|
|
1290
|
-
}
|
|
1291
|
-
if (topScore >= 45) {
|
|
1292
|
-
return { level: 'medium', score: topScore };
|
|
1293
|
-
}
|
|
1294
|
-
return { level: 'low', score: topScore };
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
|
-
function buildLowConfidenceHint(slotLabel, queriesUsed) {
|
|
1298
|
-
return `Low confidence for ${slotLabel}. Try search_icons with: ${queriesUsed.slice(0, 3).join(', ')}.`;
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
function normalizeResponseMode(responseMode) {
|
|
1302
|
-
if (responseMode === 'assets' || responseMode === 'full') return responseMode;
|
|
1303
|
-
return 'plan';
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
function isNoisyAlternative(entry) {
|
|
1307
|
-
return entry.variantPenalty >= 12 || entry.brandPenalty >= 12 || entry.slotPreferenceBonus < 0;
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
export async function recommendIconsForTask({
|
|
1311
|
-
task,
|
|
1312
|
-
library,
|
|
1313
|
-
style = 'any',
|
|
1314
|
-
locale = null,
|
|
1315
|
-
slots,
|
|
1316
|
-
limitPerSlot = 3,
|
|
1317
|
-
responseMode = 'plan',
|
|
1318
|
-
searchIconsForQuery,
|
|
1319
|
-
buildIconResult,
|
|
1320
|
-
semanticMap,
|
|
1321
|
-
}) {
|
|
1322
|
-
const normalizedResponseMode = normalizeResponseMode(responseMode);
|
|
1323
|
-
const scoredSlotResults = await mapWithConcurrency(slots, SLOT_SEARCH_CONCURRENCY, async (slotLabel) => {
|
|
1324
|
-
const intentTerms = buildSlotIntentTerms(task, slotLabel, locale);
|
|
1325
|
-
const requestedVariantTerms = dedupe([
|
|
1326
|
-
...tokenizeText(slotLabel),
|
|
1327
|
-
...buildLocalizedVariants(slotLabel, locale).flatMap(tokenizeText),
|
|
1328
|
-
...buildDirectLocalizedIntentTerms(slotLabel),
|
|
1329
|
-
]);
|
|
1330
|
-
const queryVariants =
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
const
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1408
|
+
await Promise.all(Array.from({ length: workerCount }, () => worker()));
|
|
1409
|
+
return results;
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
function getConfidence(topScore, nextScore = 0) {
|
|
1413
|
+
if (topScore >= 90 && topScore - nextScore >= 20) {
|
|
1414
|
+
return { level: 'high', score: topScore };
|
|
1415
|
+
}
|
|
1416
|
+
if (topScore >= 45) {
|
|
1417
|
+
return { level: 'medium', score: topScore };
|
|
1418
|
+
}
|
|
1419
|
+
return { level: 'low', score: topScore };
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
function buildLowConfidenceHint(slotLabel, queriesUsed) {
|
|
1423
|
+
return `Low confidence for ${slotLabel}. Try search_icons with: ${queriesUsed.slice(0, 3).join(', ')}.`;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
function normalizeResponseMode(responseMode) {
|
|
1427
|
+
if (responseMode === 'assets' || responseMode === 'full') return responseMode;
|
|
1428
|
+
return 'plan';
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
function isNoisyAlternative(entry) {
|
|
1432
|
+
return entry.variantPenalty >= 12 || entry.brandPenalty >= 12 || entry.slotPreferenceBonus < 0;
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
export async function recommendIconsForTask({
|
|
1436
|
+
task,
|
|
1437
|
+
library,
|
|
1438
|
+
style = 'any',
|
|
1439
|
+
locale = null,
|
|
1440
|
+
slots,
|
|
1441
|
+
limitPerSlot = 3,
|
|
1442
|
+
responseMode = 'plan',
|
|
1443
|
+
searchIconsForQuery,
|
|
1444
|
+
buildIconResult,
|
|
1445
|
+
semanticMap,
|
|
1446
|
+
}) {
|
|
1447
|
+
const normalizedResponseMode = normalizeResponseMode(responseMode);
|
|
1448
|
+
const scoredSlotResults = await mapWithConcurrency(slots, SLOT_SEARCH_CONCURRENCY, async (slotLabel) => {
|
|
1449
|
+
const intentTerms = buildSlotIntentTerms(task, slotLabel, locale);
|
|
1450
|
+
const requestedVariantTerms = dedupe([
|
|
1451
|
+
...tokenizeText(slotLabel),
|
|
1452
|
+
...buildLocalizedVariants(slotLabel, locale).flatMap(tokenizeText),
|
|
1453
|
+
...buildDirectLocalizedIntentTerms(slotLabel),
|
|
1454
|
+
]);
|
|
1455
|
+
const queryVariants = dedupe([
|
|
1456
|
+
...buildBrandLogoQueryVariants(task, slotLabel, library),
|
|
1457
|
+
...buildSlotQueryVariants(task, slotLabel, locale),
|
|
1458
|
+
]).slice(0, locale ? 8 : 4);
|
|
1459
|
+
const pooledIcons = [];
|
|
1460
|
+
const seen = new Set();
|
|
1461
|
+
|
|
1462
|
+
const resultGroups = await mapWithConcurrency(queryVariants, SLOT_QUERY_CONCURRENCY, async (queryVariant) => {
|
|
1463
|
+
try {
|
|
1464
|
+
return await searchIconsForQuery({
|
|
1465
|
+
query: queryVariant,
|
|
1466
|
+
library,
|
|
1467
|
+
style,
|
|
1468
|
+
limit: Math.max(limitPerSlot * 5, 10),
|
|
1469
|
+
locale,
|
|
1470
|
+
});
|
|
1471
|
+
} catch {
|
|
1472
|
+
return [];
|
|
1473
|
+
}
|
|
1474
|
+
});
|
|
1347
1475
|
|
|
1348
1476
|
for (const results of resultGroups) {
|
|
1349
1477
|
for (const icon of results) {
|
|
@@ -1355,137 +1483,139 @@ export async function recommendIconsForTask({
|
|
|
1355
1483
|
}
|
|
1356
1484
|
|
|
1357
1485
|
const scored = pooledIcons
|
|
1358
|
-
.map((icon, index) => {
|
|
1359
|
-
const semanticRecord = getSemanticRecordForIcon(semanticMap, icon);
|
|
1360
|
-
const semanticQuery = queryVariants.join(' ');
|
|
1486
|
+
.map((icon, index) => {
|
|
1487
|
+
const semanticRecord = getSemanticRecordForIcon(semanticMap, icon);
|
|
1488
|
+
const semanticQuery = queryVariants.join(' ');
|
|
1361
1489
|
const semanticScore = semanticRecord ? scoreSemanticAlignment(semanticQuery, semanticRecord) * 3 : 0;
|
|
1362
1490
|
const lexicalScore = scoreLexicalFit(icon, intentTerms, slotLabel, task);
|
|
1491
|
+
const brandLogoMatchBonus = getBrandLogoMatchBonus(icon, semanticRecord, slotLabel, task, library);
|
|
1363
1492
|
const semanticBonus = semanticRecord ? 6 : 0;
|
|
1364
|
-
const variantPenalty = getVariantPenalty(icon, requestedVariantTerms);
|
|
1365
|
-
const brandPenalty = getBrandPenalty(icon, requestedVariantTerms);
|
|
1366
|
-
const slotPreferenceBonus = getSlotPreferenceBonus(icon, slotLabel, intentTerms, library, requestedVariantTerms);
|
|
1367
|
-
const intentProfile = buildSearchIntentProfile(`${slotLabel} ${task}`);
|
|
1368
|
-
const intentAdjustment = getIntentCandidateAdjustment(icon, intentProfile);
|
|
1369
|
-
|
|
1493
|
+
const variantPenalty = getVariantPenalty(icon, requestedVariantTerms);
|
|
1494
|
+
const brandPenalty = getBrandPenalty(icon, requestedVariantTerms);
|
|
1495
|
+
const slotPreferenceBonus = getSlotPreferenceBonus(icon, slotLabel, intentTerms, library, requestedVariantTerms);
|
|
1496
|
+
const intentProfile = buildSearchIntentProfile(`${slotLabel} ${task}`);
|
|
1497
|
+
const intentAdjustment = getIntentCandidateAdjustment(icon, intentProfile);
|
|
1498
|
+
|
|
1370
1499
|
return {
|
|
1371
|
-
icon,
|
|
1372
|
-
index,
|
|
1373
|
-
semanticRecord,
|
|
1374
|
-
variantPenalty,
|
|
1375
|
-
brandPenalty,
|
|
1376
|
-
slotPreferenceBonus,
|
|
1377
|
-
totalScore:
|
|
1378
|
-
semanticScore +
|
|
1379
|
-
lexicalScore +
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
intentAdjustment.
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
.
|
|
1390
|
-
|
|
1391
|
-
if (right.
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
const
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
const
|
|
1413
|
-
const
|
|
1414
|
-
const
|
|
1415
|
-
const
|
|
1416
|
-
const
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
return
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
const
|
|
1423
|
-
|
|
1424
|
-
!
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
if (selectedEntries.
|
|
1432
|
-
if (
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
const
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
.
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
}
|
|
1500
|
+
icon,
|
|
1501
|
+
index,
|
|
1502
|
+
semanticRecord,
|
|
1503
|
+
variantPenalty,
|
|
1504
|
+
brandPenalty,
|
|
1505
|
+
slotPreferenceBonus,
|
|
1506
|
+
totalScore:
|
|
1507
|
+
semanticScore +
|
|
1508
|
+
lexicalScore +
|
|
1509
|
+
brandLogoMatchBonus +
|
|
1510
|
+
semanticBonus +
|
|
1511
|
+
slotPreferenceBonus +
|
|
1512
|
+
intentAdjustment.boost -
|
|
1513
|
+
intentAdjustment.penalty -
|
|
1514
|
+
variantPenalty -
|
|
1515
|
+
brandPenalty,
|
|
1516
|
+
};
|
|
1517
|
+
})
|
|
1518
|
+
.filter((entry) => entry.totalScore > 0)
|
|
1519
|
+
.sort((left, right) => {
|
|
1520
|
+
if (right.totalScore !== left.totalScore) return right.totalScore - left.totalScore;
|
|
1521
|
+
if (right.slotPreferenceBonus !== left.slotPreferenceBonus) {
|
|
1522
|
+
return right.slotPreferenceBonus - left.slotPreferenceBonus;
|
|
1523
|
+
}
|
|
1524
|
+
return left.index - right.index;
|
|
1525
|
+
})
|
|
1526
|
+
.slice(0, Math.max(limitPerSlot * 3, 8));
|
|
1527
|
+
|
|
1528
|
+
return {
|
|
1529
|
+
slot: slotLabel,
|
|
1530
|
+
queries_used: queryVariants,
|
|
1531
|
+
intentTerms,
|
|
1532
|
+
requestedVariantTerms,
|
|
1533
|
+
scored,
|
|
1534
|
+
};
|
|
1535
|
+
});
|
|
1536
|
+
|
|
1537
|
+
const usedIconKeys = new Set();
|
|
1538
|
+
const slotResults = [];
|
|
1539
|
+
for (const slotResult of scoredSlotResults) {
|
|
1540
|
+
const sorted = [...slotResult.scored].sort((left, right) => {
|
|
1541
|
+
const leftKey = `${left.icon.lib}:${left.icon.id}`;
|
|
1542
|
+
const rightKey = `${right.icon.lib}:${right.icon.id}`;
|
|
1543
|
+
const leftDuplicatePenalty = usedIconKeys.has(leftKey) ? 80 : 0;
|
|
1544
|
+
const rightDuplicatePenalty = usedIconKeys.has(rightKey) ? 80 : 0;
|
|
1545
|
+
const leftScore = left.totalScore - leftDuplicatePenalty;
|
|
1546
|
+
const rightScore = right.totalScore - rightDuplicatePenalty;
|
|
1547
|
+
|
|
1548
|
+
if (rightScore !== leftScore) return rightScore - leftScore;
|
|
1549
|
+
return left.index - right.index;
|
|
1550
|
+
});
|
|
1551
|
+
const selectedEntries = [];
|
|
1552
|
+
const primaryEntry = sorted.find((entry) => (
|
|
1553
|
+
!isNoisyAlternative(entry) &&
|
|
1554
|
+
!usedIconKeys.has(`${entry.icon.lib}:${entry.icon.id}`)
|
|
1555
|
+
)) || sorted.find((entry) => !isNoisyAlternative(entry)) || sorted[0];
|
|
1556
|
+
if (primaryEntry) {
|
|
1557
|
+
selectedEntries.push(primaryEntry);
|
|
1558
|
+
}
|
|
1559
|
+
for (const entry of sorted) {
|
|
1560
|
+
if (selectedEntries.length >= limitPerSlot) break;
|
|
1561
|
+
if (selectedEntries.includes(entry)) continue;
|
|
1562
|
+
if (isNoisyAlternative(entry)) continue;
|
|
1563
|
+
selectedEntries.push(entry);
|
|
1564
|
+
}
|
|
1565
|
+
const preparedCandidates = [];
|
|
1566
|
+
const preparedEntries = [];
|
|
1567
|
+
for (const [candidateIndex, entry] of selectedEntries.entries()) {
|
|
1568
|
+
const iconResult = await buildIconResult(entry.icon, { style });
|
|
1569
|
+
if (!iconResult?.svg) continue;
|
|
1570
|
+
const includeSvg = normalizedResponseMode === 'full' || (normalizedResponseMode === 'assets' && candidateIndex === 0);
|
|
1571
|
+
preparedCandidates.push(buildCandidatePayload(
|
|
1572
|
+
slotResult.slot,
|
|
1573
|
+
iconResult,
|
|
1574
|
+
entry.semanticRecord,
|
|
1575
|
+
slotResult.intentTerms,
|
|
1576
|
+
normalizedResponseMode,
|
|
1577
|
+
includeSvg,
|
|
1578
|
+
normalizedResponseMode !== 'plan' || candidateIndex === 0
|
|
1579
|
+
));
|
|
1580
|
+
preparedEntries.push(entry);
|
|
1581
|
+
}
|
|
1582
|
+
const chosen = preparedEntries[0] || primaryEntry || null;
|
|
1583
|
+
if (chosen) {
|
|
1584
|
+
usedIconKeys.add(`${chosen.icon.lib}:${chosen.icon.id}`);
|
|
1585
|
+
}
|
|
1586
|
+
const confidence = chosen
|
|
1587
|
+
? getConfidence(chosen.totalScore, sorted[1]?.totalScore || 0)
|
|
1588
|
+
: { level: 'low', score: 0 };
|
|
1589
|
+
|
|
1590
|
+
const slotPayload = {
|
|
1591
|
+
slot: slotResult.slot,
|
|
1592
|
+
confidence,
|
|
1593
|
+
recommended: preparedCandidates[0] || null,
|
|
1594
|
+
alternatives: preparedCandidates.slice(1),
|
|
1595
|
+
};
|
|
1596
|
+
if (confidence.level === 'low') {
|
|
1597
|
+
slotPayload.guidance = buildLowConfidenceHint(slotResult.slot, slotResult.queries_used);
|
|
1598
|
+
}
|
|
1599
|
+
if (normalizedResponseMode !== 'plan') {
|
|
1600
|
+
slotPayload.queries_used = slotResult.queries_used;
|
|
1601
|
+
}
|
|
1602
|
+
slotResults.push(slotPayload);
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
const lowConfidenceSlots = slotResults
|
|
1606
|
+
.filter((slot) => !slot.recommended || slot.confidence?.level === 'low')
|
|
1607
|
+
.map((slot) => slot.slot);
|
|
1608
|
+
const allSlotsResolved = slotResults.every((slot) => Boolean(slot.recommended));
|
|
1609
|
+
|
|
1610
|
+
return {
|
|
1611
|
+
task,
|
|
1612
|
+
library: library || 'all',
|
|
1613
|
+
style,
|
|
1614
|
+
response_mode: normalizedResponseMode,
|
|
1615
|
+
slot_count: slots.length,
|
|
1616
|
+
all_slots_resolved: allSlotsResolved,
|
|
1617
|
+
low_confidence_slots: lowConfidenceSlots,
|
|
1618
|
+
fallback_recommended: !allSlotsResolved || lowConfidenceSlots.length > 0,
|
|
1619
|
+
results: slotResults,
|
|
1620
|
+
};
|
|
1621
|
+
}
|