@cavuno/board 1.25.0 → 1.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +88 -0
  2. package/dist/bin.mjs +67 -34
  3. package/dist/filters.d.mts +55 -0
  4. package/dist/filters.d.ts +55 -0
  5. package/dist/filters.js +193 -0
  6. package/dist/filters.mjs +170 -0
  7. package/dist/format.d.mts +240 -0
  8. package/dist/format.d.ts +240 -0
  9. package/dist/format.js +453 -0
  10. package/dist/format.mjs +430 -0
  11. package/dist/index.d.mts +81 -3965
  12. package/dist/index.d.ts +81 -3965
  13. package/dist/index.js +154 -7
  14. package/dist/index.mjs +151 -4
  15. package/dist/jobs-DK5mPBgq.d.mts +3836 -0
  16. package/dist/jobs-DK5mPBgq.d.ts +3836 -0
  17. package/dist/salaries-CXt6Vkrp.d.ts +130 -0
  18. package/dist/salaries-CrJsaZe6.d.mts +130 -0
  19. package/dist/seo.d.mts +288 -0
  20. package/dist/seo.d.ts +288 -0
  21. package/dist/seo.js +1102 -0
  22. package/dist/seo.mjs +1079 -0
  23. package/dist/sitemap.d.mts +63 -0
  24. package/dist/sitemap.d.ts +63 -0
  25. package/dist/sitemap.js +353 -0
  26. package/dist/sitemap.mjs +330 -0
  27. package/dist/theme.d.mts +63 -0
  28. package/dist/theme.d.ts +63 -0
  29. package/dist/theme.js +149 -0
  30. package/dist/theme.mjs +128 -0
  31. package/package.json +57 -2
  32. package/skills/cavuno-board-account/SKILL.md +147 -0
  33. package/skills/cavuno-board-applications/SKILL.md +110 -0
  34. package/skills/cavuno-board-blog/SKILL.md +99 -0
  35. package/skills/cavuno-board-companies/SKILL.md +99 -0
  36. package/skills/cavuno-board-filters/SKILL.md +89 -0
  37. package/skills/cavuno-board-format/SKILL.md +104 -0
  38. package/skills/cavuno-board-job-alerts/SKILL.md +115 -0
  39. package/skills/cavuno-board-job-posting/SKILL.md +130 -0
  40. package/skills/cavuno-board-jobs/SKILL.md +15 -0
  41. package/skills/cavuno-board-messaging/SKILL.md +121 -0
  42. package/skills/cavuno-board-paywall/SKILL.md +108 -0
  43. package/skills/cavuno-board-salaries/SKILL.md +87 -0
  44. package/skills/cavuno-board-seo/SKILL.md +180 -0
  45. package/skills/cavuno-board-setup/SKILL.md +26 -2
  46. package/skills/cavuno-board-sitemap/SKILL.md +147 -0
  47. package/skills/cavuno-board-smoke-test/SKILL.md +84 -0
  48. package/skills/cavuno-board-theme/SKILL.md +69 -0
  49. package/skills/manifest.json +106 -1
@@ -0,0 +1,430 @@
1
+ // src/format/dates.ts
2
+ var rtfNarrowCache = /* @__PURE__ */ new Map();
3
+ var dtfCache = /* @__PURE__ */ new Map();
4
+ function getNarrowRelativeTimeFormat(language) {
5
+ const key = language ?? "en";
6
+ let rtf = rtfNarrowCache.get(key);
7
+ if (!rtf) {
8
+ rtf = new Intl.RelativeTimeFormat(key, {
9
+ numeric: "always",
10
+ style: "narrow"
11
+ });
12
+ rtfNarrowCache.set(key, rtf);
13
+ }
14
+ return rtf;
15
+ }
16
+ function getDateTimeFormat(language) {
17
+ const key = language ?? "en";
18
+ let dtf = dtfCache.get(key);
19
+ if (!dtf) {
20
+ dtf = new Intl.DateTimeFormat(key, {
21
+ dateStyle: "medium",
22
+ timeZone: "UTC"
23
+ });
24
+ dtfCache.set(key, dtf);
25
+ }
26
+ return dtf;
27
+ }
28
+ function formatNarrow(value, unit, language) {
29
+ try {
30
+ return getNarrowRelativeTimeFormat(language).format(value, unit);
31
+ } catch {
32
+ const shortMap = {
33
+ year: "y",
34
+ month: "mo",
35
+ week: "w",
36
+ day: "d",
37
+ hour: "h",
38
+ minute: "m",
39
+ second: "s"
40
+ };
41
+ return `${Math.abs(value)}${shortMap[unit] ?? unit}`;
42
+ }
43
+ }
44
+ function formatDate(locale, value) {
45
+ if (!value) return null;
46
+ const parsed = new Date(value);
47
+ if (Number.isNaN(parsed.getTime())) return null;
48
+ try {
49
+ return getDateTimeFormat(locale).format(parsed);
50
+ } catch {
51
+ return parsed.toISOString().split("T")[0];
52
+ }
53
+ }
54
+ function formatPublishedRelativeDate(locale, value, referenceNowMs = Date.now()) {
55
+ if (!value) return null;
56
+ const parsed = new Date(value);
57
+ if (Number.isNaN(parsed.getTime())) return null;
58
+ const diff = referenceNowMs - parsed.getTime();
59
+ const absDiff = Math.abs(diff);
60
+ const minute = 60 * 1e3;
61
+ const hour = 60 * minute;
62
+ const day = 24 * hour;
63
+ const week = 7 * day;
64
+ const month = 30 * day;
65
+ const year = 365 * day;
66
+ if (absDiff < minute) {
67
+ return "now";
68
+ }
69
+ const units = [
70
+ { unit: "year", ms: year },
71
+ { unit: "month", ms: month },
72
+ { unit: "week", ms: week },
73
+ { unit: "day", ms: day },
74
+ { unit: "hour", ms: hour },
75
+ { unit: "minute", ms: minute }
76
+ ];
77
+ for (const candidate of units) {
78
+ if (absDiff >= candidate.ms) {
79
+ const valueInUnit = Math.round(absDiff / candidate.ms);
80
+ const direction2 = diff >= 0 ? -valueInUnit : valueInUnit;
81
+ return formatNarrow(direction2, candidate.unit, locale);
82
+ }
83
+ }
84
+ const seconds = Math.round(absDiff / 1e3);
85
+ const direction = diff >= 0 ? -seconds : seconds;
86
+ return formatNarrow(direction, "second", locale);
87
+ }
88
+ function formatMonthYear(locale, dateStr) {
89
+ const date = /* @__PURE__ */ new Date(dateStr + "T00:00:00");
90
+ return date.toLocaleDateString(locale, {
91
+ month: "short",
92
+ year: "numeric"
93
+ });
94
+ }
95
+
96
+ // src/format/salary-lexicon.ts
97
+ var EN = {
98
+ timeframe: {
99
+ per_year: "Yearly",
100
+ per_month: "Monthly",
101
+ per_week: "Weekly",
102
+ per_day: "Daily",
103
+ per_hour: "Hourly"
104
+ },
105
+ rangePrefix: { from: "From", upTo: "Up to" },
106
+ seniority: {
107
+ entry_level: "Entry level",
108
+ associate: "Associate",
109
+ mid_level: "Mid-level",
110
+ senior: "Senior",
111
+ lead: "Lead",
112
+ principal: "Principal",
113
+ director: "Director",
114
+ executive: "Executive"
115
+ },
116
+ frames: {
117
+ entitySalariesTitle: ({ entity, range }) => `${entity} Salaries (${range}/yr)`,
118
+ salariesInPlaceTitle: ({ place, range }) => `Salaries in ${place} (${range}/yr)`,
119
+ salariesInPlaceTitleNoRange: ({ place }) => `Salaries in ${place}`,
120
+ entitySalariesInPlaceTitle: ({ entity, place, range }) => `${entity} Salaries in ${place} (${range}/yr)`,
121
+ companySalariesTitle: ({ company, range }) => `${company} Salaries${range ? ` (${range}/yr)` : ""}`,
122
+ companyCategorySalariesTitle: ({ company, category, range }) => `${company} ${category} Salaries${range ? ` (${range}/yr)` : ""}`,
123
+ professionalsEarn: ({ entity, range, count }) => `${entity} professionals earn ${range}/yr on average across ${count} job postings.`,
124
+ rolesPay: ({ entity, range, count }) => `${entity} roles pay ${range}/yr on average across ${count} job postings.`,
125
+ professionalsInLocationEarn: ({ entity, place, range, count }) => `${entity} professionals in ${place} earn ${range}/yr on average across ${count} job postings.`,
126
+ seniorityRange: ({ lowLabel, lowAmount, highLabel, highAmount }) => `${lowLabel} roles start at ${lowAmount}, ${highLabel} roles reach ${highAmount}.`,
127
+ seniorityRangeWhile: ({ lowLabel, lowAmount, highLabel, highAmount }) => `${lowLabel} salaries start at ${lowAmount}, while ${highLabel} roles reach ${highAmount}.`,
128
+ compareAcrossTopPaying: ({ count }) => `Compare across ${count} top-paying ${count === 1 ? "company" : "companies"}.`,
129
+ compareAcrossTop: ({ count }) => `Compare across ${count} top ${count === 1 ? "company" : "companies"}.`,
130
+ boardWideAverage: ({ entity, range }) => `Board-wide ${entity} average: ${range}/yr.`,
131
+ averageSalaryInCity: ({ place, range, count }) => `Average salary in ${place} is ${range}/yr across ${count} jobs. Browse salary data by title and skill.`,
132
+ browseLocationsInRegion: ({ count, place }) => `Browse salary data across ${count} locations in ${place}. Compare salaries by title, skill, and company.`,
133
+ companyPays: ({ company, range, count }) => `${company} pays ${range}/yr on average across ${count} job postings.`,
134
+ breakdownAcrossCategories: ({ count }) => `Breakdown across ${count} job ${count === 1 ? "category" : "categories"}.`,
135
+ compareWithSimilar: ({ count }) => `Compare with ${count} similar ${count === 1 ? "company" : "companies"}.`,
136
+ salaryInfoFor: ({ company, board }) => `Salary information for ${company} on ${board}.`,
137
+ categoryRolesAtCompanyPay: ({ category, company, range, count }) => `${category} roles at ${company} pay ${range}/yr based on ${count} job postings.`,
138
+ categorySalaryDataFor: ({ category, company, board }) => `${category} salary data for ${company} on ${board}.`
139
+ }
140
+ };
141
+ var DE = {
142
+ timeframe: {
143
+ per_year: "pro Jahr",
144
+ per_month: "pro Monat",
145
+ per_week: "pro Woche",
146
+ per_day: "pro Tag",
147
+ per_hour: "pro Stunde"
148
+ },
149
+ rangePrefix: { from: "ab", upTo: "bis zu" },
150
+ seniority: {
151
+ entry_level: "Entry-Level",
152
+ associate: "Associate",
153
+ mid_level: "Mid-Level",
154
+ senior: "Senior",
155
+ lead: "Lead",
156
+ principal: "Principal",
157
+ director: "Director",
158
+ executive: "F\xFChrungskraft"
159
+ },
160
+ frames: {
161
+ entitySalariesTitle: ({ entity, range }) => `${entity} Geh\xE4lter (${range}/Jahr)`,
162
+ salariesInPlaceTitle: ({ place, range }) => `Geh\xE4lter in ${place} (${range}/Jahr)`,
163
+ salariesInPlaceTitleNoRange: ({ place }) => `Geh\xE4lter in ${place}`,
164
+ entitySalariesInPlaceTitle: ({ entity, place, range }) => `${entity} Geh\xE4lter in ${place} (${range}/Jahr)`,
165
+ companySalariesTitle: ({ company, range }) => `${company} Geh\xE4lter${range ? ` (${range}/Jahr)` : ""}`,
166
+ companyCategorySalariesTitle: ({ company, category, range }) => `${company} ${category} Geh\xE4lter${range ? ` (${range}/Jahr)` : ""}`,
167
+ professionalsEarn: ({ entity, range, count }) => `${entity}-Fachkr\xE4fte verdienen durchschnittlich ${range}/Jahr, basierend auf ${count} Stellenanzeigen.`,
168
+ rolesPay: ({ entity, range, count }) => `${entity}-Positionen werden mit durchschnittlich ${range}/Jahr verg\xFCtet, basierend auf ${count} Stellenanzeigen.`,
169
+ professionalsInLocationEarn: ({ entity, place, range, count }) => `${entity}-Fachkr\xE4fte in ${place} verdienen durchschnittlich ${range}/Jahr, basierend auf ${count} Stellenanzeigen.`,
170
+ seniorityRange: ({ lowLabel, lowAmount, highLabel, highAmount }) => `${lowLabel}-Positionen beginnen bei ${lowAmount}, ${highLabel}-Positionen erreichen ${highAmount}.`,
171
+ seniorityRangeWhile: ({ lowLabel, lowAmount, highLabel, highAmount }) => `${lowLabel}-Geh\xE4lter beginnen bei ${lowAmount}, w\xE4hrend ${highLabel}-Positionen ${highAmount} erreichen.`,
172
+ compareAcrossTopPaying: ({ count }) => `Vergleichen Sie ${count} ${count === 1 ? "bestzahlendes" : "bestzahlende"} Unternehmen.`,
173
+ compareAcrossTop: ({ count }) => `Vergleichen Sie ${count} Top-Unternehmen.`,
174
+ boardWideAverage: ({ entity, range }) => `Gesamtdurchschnitt ${entity}: ${range}/Jahr.`,
175
+ averageSalaryInCity: ({ place, range, count }) => `Das Durchschnittsgehalt in ${place} betr\xE4gt ${range}/Jahr, basierend auf ${count} Stellen. Gehaltsdaten nach Titel und F\xE4higkeiten durchsuchen.`,
176
+ browseLocationsInRegion: ({ count, place }) => `Gehaltsdaten f\xFCr ${count} Standorte in ${place} durchsuchen. Geh\xE4lter nach Titel, F\xE4higkeiten und Unternehmen vergleichen.`,
177
+ companyPays: ({ company, range, count }) => `${company} zahlt durchschnittlich ${range}/Jahr, basierend auf ${count} Stellenanzeigen.`,
178
+ breakdownAcrossCategories: ({ count }) => `Aufschl\xFCsselung \xFCber ${count} Job-${count === 1 ? "Kategorie" : "Kategorien"}.`,
179
+ compareWithSimilar: ({ count }) => `Vergleichen Sie mit ${count} \xE4hnlichen Unternehmen.`,
180
+ salaryInfoFor: ({ company, board }) => `Gehaltsinformationen f\xFCr ${company} auf ${board}.`,
181
+ categoryRolesAtCompanyPay: ({ category, company, range, count }) => `${category}-Positionen bei ${company} werden mit ${range}/Jahr verg\xFCtet, basierend auf ${count} Stellenanzeigen.`,
182
+ categorySalaryDataFor: ({ category, company, board }) => `${category}-Gehaltsdaten f\xFCr ${company} auf ${board}.`
183
+ }
184
+ };
185
+ var LEXICONS = { en: EN, de: DE };
186
+ function getSalaryLexicon(locale) {
187
+ return locale && LEXICONS[locale] || EN;
188
+ }
189
+
190
+ // src/format/labels.ts
191
+ var EN_LABELS = {
192
+ // remoteOption
193
+ on_site: "On-site",
194
+ hybrid: "Hybrid",
195
+ remote: "Remote",
196
+ // employmentType
197
+ full_time: "Full-time",
198
+ part_time: "Part-time",
199
+ contract: "Contract",
200
+ internship: "Internship",
201
+ temporary: "Temporary",
202
+ volunteer: "Volunteer",
203
+ other: "Other"
204
+ };
205
+ var SENIORITY_KEYS = /* @__PURE__ */ new Set([
206
+ "entry_level",
207
+ "associate",
208
+ "mid_level",
209
+ "senior",
210
+ "lead",
211
+ "principal",
212
+ "director",
213
+ "executive"
214
+ ]);
215
+ function fieldLabel(locale, value) {
216
+ if (!value) return null;
217
+ if (SENIORITY_KEYS.has(value)) {
218
+ return getSalaryLexicon(locale).seniority[value];
219
+ }
220
+ return EN_LABELS[value] ?? value;
221
+ }
222
+
223
+ // src/format/location.ts
224
+ function locationLabel(locale, job) {
225
+ const office = job.officeLocations[0];
226
+ const place = office ? office.displayName ?? [office.city ?? office.locality, office.country].filter(Boolean).join(", ") : null;
227
+ if (job.remoteOption === "remote") {
228
+ return job.remoteWorldwide ? "Remote (worldwide)" : "Remote";
229
+ }
230
+ if (!place) return fieldLabel(locale, job.remoteOption) ?? "";
231
+ return job.remoteOption === "hybrid" ? `${place} (hybrid)` : place;
232
+ }
233
+ function cardLocationLabel(locale, job) {
234
+ if (job.remoteOption === "remote") {
235
+ return job.remoteLocationLabel ? `Remote \xB7 ${job.remoteLocationLabel}` : "Remote";
236
+ }
237
+ return job.locationLabel ?? fieldLabel(locale, job.remoteOption) ?? "";
238
+ }
239
+
240
+ // src/format/job-card.ts
241
+ function fullJobToCard(locale, job) {
242
+ return {
243
+ id: job.id,
244
+ object: "job_card",
245
+ slug: job.slug ?? "",
246
+ title: job.title,
247
+ publishedAt: job.publishedAt,
248
+ employmentType: job.employmentType,
249
+ remoteOption: job.remoteOption,
250
+ remoteLocationLabel: job.remoteWorldwide ? "Worldwide" : null,
251
+ salaryMin: job.salaryMin,
252
+ salaryMax: job.salaryMax,
253
+ salaryCurrency: job.salaryCurrency,
254
+ salaryTimeframe: job.salaryTimeframe,
255
+ isFeatured: job.isFeatured,
256
+ locationLabel: locationLabel(locale, job),
257
+ company: job.company?.slug ? {
258
+ slug: job.company.slug,
259
+ name: job.company.name ?? "",
260
+ logoUrl: job.company.logoUrl
261
+ } : null,
262
+ categories: job.categories,
263
+ skills: job.skills,
264
+ links: job.links
265
+ };
266
+ }
267
+
268
+ // src/format/salary-range.ts
269
+ var CURRENCY_SYMBOLS = {
270
+ USD: "$",
271
+ EUR: "\u20AC",
272
+ GBP: "\xA3",
273
+ JPY: "\xA5",
274
+ CNY: "\xA5",
275
+ KRW: "\u20A9",
276
+ INR: "\u20B9",
277
+ RUB: "\u20BD",
278
+ BRL: "R$",
279
+ CAD: "C$",
280
+ AUD: "A$",
281
+ CHF: "CHF ",
282
+ SEK: "kr ",
283
+ NOK: "kr ",
284
+ DKK: "kr ",
285
+ PLN: "z\u0142 ",
286
+ MXN: "MX$",
287
+ SGD: "S$",
288
+ HKD: "HK$",
289
+ NZD: "NZ$",
290
+ ZAR: "R ",
291
+ THB: "\u0E3F",
292
+ PHP: "\u20B1",
293
+ IDR: "Rp ",
294
+ MYR: "RM ",
295
+ VND: "\u20AB",
296
+ AED: "AED ",
297
+ SAR: "SAR ",
298
+ ILS: "\u20AA",
299
+ TRY: "\u20BA",
300
+ CZK: "K\u010D ",
301
+ HUF: "Ft ",
302
+ RON: "lei ",
303
+ BGN: "\u043B\u0432 ",
304
+ HRK: "kn ",
305
+ ISK: "kr ",
306
+ CLP: "CLP$",
307
+ COP: "COP$",
308
+ PEN: "S/",
309
+ ARS: "ARS$",
310
+ TWD: "NT$",
311
+ NGN: "\u20A6",
312
+ EGP: "E\xA3",
313
+ PKR: "\u20A8",
314
+ BDT: "\u09F3",
315
+ UAH: "\u20B4",
316
+ KZT: "\u20B8"
317
+ };
318
+ function getCurrencySymbol(currency) {
319
+ if (!currency) {
320
+ return "$";
321
+ }
322
+ const normalized = currency.trim().toUpperCase();
323
+ return CURRENCY_SYMBOLS[normalized] ?? `${normalized} `;
324
+ }
325
+ var compactFormatCache = /* @__PURE__ */ new Map();
326
+ function getCompactFormatter(language) {
327
+ const cached = compactFormatCache.get(language);
328
+ if (cached) return cached;
329
+ const formatter = new Intl.NumberFormat(language, {
330
+ notation: "compact",
331
+ compactDisplay: "short",
332
+ maximumFractionDigits: 1
333
+ });
334
+ compactFormatCache.set(language, formatter);
335
+ return formatter;
336
+ }
337
+ function formatCompactNumber(value, language) {
338
+ try {
339
+ return getCompactFormatter(language ?? "en").format(value);
340
+ } catch {
341
+ if (value >= 1e6) {
342
+ const millions = value / 1e6;
343
+ return millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;
344
+ }
345
+ if (value >= 1e3) {
346
+ const thousands = value / 1e3;
347
+ return thousands % 1 === 0 ? `${thousands}k` : `${thousands.toFixed(1)}k`;
348
+ }
349
+ return value.toString();
350
+ }
351
+ }
352
+ var compactCurrencyCache = /* @__PURE__ */ new Map();
353
+ function formatCompactCurrency(value, language, currency) {
354
+ const currencyCode = (currency ?? "USD").trim().toUpperCase();
355
+ const cacheKey = `${language}:${currencyCode}`;
356
+ let formatter = compactCurrencyCache.get(cacheKey);
357
+ if (formatter === void 0) {
358
+ try {
359
+ formatter = new Intl.NumberFormat(language, {
360
+ style: "currency",
361
+ currency: currencyCode,
362
+ notation: "compact",
363
+ compactDisplay: "short",
364
+ maximumFractionDigits: 1
365
+ });
366
+ } catch {
367
+ formatter = null;
368
+ }
369
+ compactCurrencyCache.set(cacheKey, formatter);
370
+ }
371
+ if (!formatter) {
372
+ return `${getCurrencySymbol(currency)}${formatCompactNumber(value, language)}`;
373
+ }
374
+ return formatter.format(value);
375
+ }
376
+ function appendTimeframe(value, timeframeLabel) {
377
+ if (!value) {
378
+ return null;
379
+ }
380
+ if (!timeframeLabel) {
381
+ return value;
382
+ }
383
+ return `${value} ${timeframeLabel}`;
384
+ }
385
+ function formatSalaryRange(language, min, max, timeframe, currency = null, timeframeOverrides) {
386
+ if (min == null && max == null) {
387
+ return null;
388
+ }
389
+ const locale = language ?? "en";
390
+ const lexicon = getSalaryLexicon(locale);
391
+ const overrideMap = {
392
+ per_year: timeframeOverrides?.yearlyLabel,
393
+ per_month: timeframeOverrides?.monthlyLabel,
394
+ per_week: timeframeOverrides?.weeklyLabel,
395
+ per_day: timeframeOverrides?.dailyLabel,
396
+ per_hour: timeframeOverrides?.hourlyLabel
397
+ };
398
+ const rawOverride = timeframe ? overrideMap[timeframe] : void 0;
399
+ const enSourceWord = timeframe ? getSalaryLexicon("en").timeframe[timeframe] : void 0;
400
+ const lexiconTimeframe = timeframe ? lexicon.timeframe[timeframe] ?? null : null;
401
+ const timeframeLabel = rawOverride && rawOverride !== enSourceWord ? rawOverride : lexiconTimeframe;
402
+ const formatAmount = locale === "en" ? (value) => `${getCurrencySymbol(currency)}${formatCompactNumber(value, locale)}` : (value) => formatCompactCurrency(value, locale, currency);
403
+ if (min != null && max != null) {
404
+ return appendTimeframe(
405
+ `${formatAmount(min)} \u2013 ${formatAmount(max)}`,
406
+ timeframeLabel
407
+ );
408
+ }
409
+ if (min != null) {
410
+ return appendTimeframe(
411
+ `${lexicon.rangePrefix.from} ${formatAmount(min)}`,
412
+ timeframeLabel
413
+ );
414
+ }
415
+ return appendTimeframe(
416
+ `${lexicon.rangePrefix.upTo} ${formatAmount(max)}`,
417
+ timeframeLabel
418
+ );
419
+ }
420
+ export {
421
+ cardLocationLabel,
422
+ fieldLabel,
423
+ formatDate,
424
+ formatMonthYear,
425
+ formatPublishedRelativeDate,
426
+ formatSalaryRange,
427
+ fullJobToCard,
428
+ getSalaryLexicon,
429
+ locationLabel
430
+ };