@cavuno/board 3.2.0 → 4.0.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 (77) hide show
  1. package/CHANGELOG.md +406 -0
  2. package/README.md +6 -2
  3. package/dist/{_spec-nkWAraS0.d.mts → _spec-GVe6WAfT.d.mts} +68 -59
  4. package/dist/{_spec-nkWAraS0.d.ts → _spec-GVe6WAfT.d.ts} +68 -59
  5. package/dist/bin.mjs +7 -2
  6. package/dist/{blog-iV9XEIGf.d.ts → blog-BsmKizpd.d.ts} +1 -1
  7. package/dist/{blog-DGBHmExV.d.mts → blog-Cf64mI8A.d.mts} +1 -1
  8. package/dist/{board-BJbXd_9_.d.mts → board-DUhgiacm.d.ts} +7 -6
  9. package/dist/{board-JhdUWIoq.d.ts → board-GGWJ4coe.d.mts} +7 -6
  10. package/dist/breadcrumbs-DFKr0HzU.d.mts +372 -0
  11. package/dist/breadcrumbs-DiccJhk4.d.ts +372 -0
  12. package/dist/chunk-BGKNXG4H.mjs +146 -0
  13. package/dist/{chunk-NXY3OWGF.mjs → chunk-T2KC6XGV.mjs} +1 -1
  14. package/dist/{chunk-STE77MAT.mjs → chunk-YEAQ3JEI.mjs} +143 -134
  15. package/dist/doctor.js +1 -1
  16. package/dist/doctor.mjs +1 -1
  17. package/dist/filters.d.mts +25 -20
  18. package/dist/filters.d.ts +25 -20
  19. package/dist/filters.js +3 -692
  20. package/dist/filters.mjs +3 -29
  21. package/dist/format.d.mts +57 -231
  22. package/dist/format.d.ts +57 -231
  23. package/dist/format.js +327 -968
  24. package/dist/format.mjs +207 -264
  25. package/dist/go.js +11 -1
  26. package/dist/go.mjs +1 -1
  27. package/dist/index.d.mts +23 -76
  28. package/dist/index.d.ts +23 -76
  29. package/dist/index.js +11 -36
  30. package/dist/index.mjs +11 -36
  31. package/dist/{jobs-BiEvL9d7.d.ts → jobs-BuLpV8iy.d.mts} +4 -4
  32. package/dist/{jobs-lVvKCBCU.d.mts → jobs-QrbXOYB9.d.ts} +4 -4
  33. package/dist/paths.d.mts +89 -1
  34. package/dist/paths.d.ts +89 -1
  35. package/dist/paths.js +62 -14
  36. package/dist/paths.mjs +11 -3
  37. package/dist/route-contract.js +23 -13
  38. package/dist/route-contract.mjs +2 -2
  39. package/dist/{search-CyRvVMUp.d.ts → search-Cr4noJJZ.d.mts} +14 -3
  40. package/dist/{search-CCyFWPi3.d.mts → search-DdsniXQv.d.ts} +14 -3
  41. package/dist/seo.d.mts +30 -29
  42. package/dist/seo.d.ts +30 -29
  43. package/dist/seo.js +197 -718
  44. package/dist/seo.mjs +26 -24
  45. package/dist/server.d.mts +5 -5
  46. package/dist/server.d.ts +5 -5
  47. package/dist/sitemap.d.mts +5 -5
  48. package/dist/sitemap.d.ts +5 -5
  49. package/dist/sitemap.js +25 -14
  50. package/dist/sitemap.mjs +3 -2
  51. package/dist/skills.js +1 -1
  52. package/dist/skills.mjs +1 -1
  53. package/dist/suggest.d.mts +2 -2
  54. package/dist/suggest.d.ts +2 -2
  55. package/dist/suggest.js +17 -3
  56. package/dist/suggest.mjs +17 -3
  57. package/dist/well-known.js +23 -13
  58. package/dist/well-known.mjs +2 -2
  59. package/package.json +2 -4
  60. package/skills/cavuno-board-applications/SKILL.md +4 -1
  61. package/skills/cavuno-board-filters/SKILL.md +11 -12
  62. package/skills/cavuno-board-format/SKILL.md +68 -56
  63. package/skills/cavuno-board-i18n/SKILL.md +102 -21
  64. package/skills/cavuno-board-search-suggestions/SKILL.md +8 -3
  65. package/skills/cavuno-board-seo/BLOG.md +4 -1
  66. package/skills/cavuno-board-seo/JOB_AND_BREADCRUMBS.md +5 -2
  67. package/skills/cavuno-board-seo/LISTING.md +35 -12
  68. package/skills/cavuno-board-seo/SALARY.md +83 -18
  69. package/skills/cavuno-board-seo/SKILL.md +3 -2
  70. package/skills/manifest.json +3 -3
  71. package/dist/breadcrumbs-1hMjcsqA.d.mts +0 -171
  72. package/dist/breadcrumbs-DexU07TT.d.ts +0 -171
  73. package/dist/chunk-IJCJ26SQ.mjs +0 -596
  74. package/dist/chunk-L7ZOYWHW.mjs +0 -98
  75. package/dist/chunk-LUGJWOT7.mjs +0 -96
  76. package/dist/ui-copy-CCkz6CVF.d.mts +0 -230
  77. package/dist/ui-copy-CCkz6CVF.d.ts +0 -230
package/dist/filters.js CHANGED
@@ -27,682 +27,9 @@ __export(filters_exports, {
27
27
  SENIORITIES: () => SENIORITIES,
28
28
  parseCompany: () => parseCompany,
29
29
  parseListingFilters: () => parseListingFilters,
30
- parseSeniority: () => parseSeniority,
31
- seniorityLabels: () => seniorityLabels,
32
- sortLabels: () => sortLabels
30
+ parseSeniority: () => parseSeniority
33
31
  });
34
32
  module.exports = __toCommonJS(filters_exports);
35
-
36
- // src/format/salary-lexicon.ts
37
- var EN = {
38
- timeframe: {
39
- per_year: "Yearly",
40
- per_month: "Monthly",
41
- per_week: "Weekly",
42
- per_day: "Daily",
43
- per_hour: "Hourly"
44
- },
45
- rangePrefix: { from: "From", upTo: "Up to" },
46
- seniority: {
47
- entry_level: "Entry level",
48
- associate: "Associate",
49
- mid_level: "Mid-level",
50
- senior: "Senior",
51
- lead: "Lead",
52
- principal: "Principal",
53
- director: "Director",
54
- executive: "Executive"
55
- },
56
- frames: {
57
- entitySalariesTitle: ({ entity, range }) => `${entity} Salaries (${range}/yr)`,
58
- salariesInPlaceTitle: ({ place, range }) => `Salaries in ${place} (${range}/yr)`,
59
- salariesInPlaceTitleNoRange: ({ place }) => `Salaries in ${place}`,
60
- entitySalariesInPlaceTitle: ({ entity, place, range }) => `${entity} Salaries in ${place} (${range}/yr)`,
61
- companySalariesTitle: ({ company, range }) => `${company} Salaries${range ? ` (${range}/yr)` : ""}`,
62
- companyCategorySalariesTitle: ({ company, category, range }) => `${company} ${category} Salaries${range ? ` (${range}/yr)` : ""}`,
63
- professionalsEarn: ({ entity, range, count }) => `${entity} professionals earn ${range}/yr on average across ${count} job postings.`,
64
- rolesPay: ({ entity, range, count }) => `${entity} roles pay ${range}/yr on average across ${count} job postings.`,
65
- professionalsInLocationEarn: ({ entity, place, range, count }) => `${entity} professionals in ${place} earn ${range}/yr on average across ${count} job postings.`,
66
- seniorityRange: ({ lowLabel, lowAmount, highLabel, highAmount }) => `${lowLabel} roles start at ${lowAmount}, ${highLabel} roles reach ${highAmount}.`,
67
- seniorityRangeWhile: ({ lowLabel, lowAmount, highLabel, highAmount }) => `${lowLabel} salaries start at ${lowAmount}, while ${highLabel} roles reach ${highAmount}.`,
68
- compareAcrossTopPaying: ({ count }) => `Compare across ${count} top-paying ${count === 1 ? "company" : "companies"}.`,
69
- compareAcrossTop: ({ count }) => `Compare across ${count} top ${count === 1 ? "company" : "companies"}.`,
70
- boardWideAverage: ({ entity, range }) => `Board-wide ${entity} average: ${range}/yr.`,
71
- averageSalaryInCity: ({ place, range, count }) => `Average salary in ${place} is ${range}/yr across ${count} jobs. Browse salary data by title and skill.`,
72
- browseLocationsInRegion: ({ count, place }) => `Browse salary data across ${count} locations in ${place}. Compare salaries by title, skill, and company.`,
73
- companyPays: ({ company, range, count }) => `${company} pays ${range}/yr on average across ${count} job postings.`,
74
- breakdownAcrossCategories: ({ count }) => `Breakdown across ${count} job ${count === 1 ? "category" : "categories"}.`,
75
- compareWithSimilar: ({ count }) => `Compare with ${count} similar ${count === 1 ? "company" : "companies"}.`,
76
- salaryInfoFor: ({ company, board }) => `Salary information for ${company} on ${board}.`,
77
- categoryRolesAtCompanyPay: ({ category, company, range, count }) => `${category} roles at ${company} pay ${range}/yr based on ${count} job postings.`,
78
- categorySalaryDataFor: ({ category, company, board }) => `${category} salary data for ${company} on ${board}.`
79
- }
80
- };
81
- var DE = {
82
- timeframe: {
83
- per_year: "pro Jahr",
84
- per_month: "pro Monat",
85
- per_week: "pro Woche",
86
- per_day: "pro Tag",
87
- per_hour: "pro Stunde"
88
- },
89
- rangePrefix: { from: "ab", upTo: "bis zu" },
90
- seniority: {
91
- entry_level: "Entry-Level",
92
- associate: "Associate",
93
- mid_level: "Mid-Level",
94
- senior: "Senior",
95
- lead: "Lead",
96
- principal: "Principal",
97
- director: "Director",
98
- executive: "F\xFChrungskraft"
99
- },
100
- frames: {
101
- entitySalariesTitle: ({ entity, range }) => `${entity} Geh\xE4lter (${range}/Jahr)`,
102
- salariesInPlaceTitle: ({ place, range }) => `Geh\xE4lter in ${place} (${range}/Jahr)`,
103
- salariesInPlaceTitleNoRange: ({ place }) => `Geh\xE4lter in ${place}`,
104
- entitySalariesInPlaceTitle: ({ entity, place, range }) => `${entity} Geh\xE4lter in ${place} (${range}/Jahr)`,
105
- companySalariesTitle: ({ company, range }) => `${company} Geh\xE4lter${range ? ` (${range}/Jahr)` : ""}`,
106
- companyCategorySalariesTitle: ({ company, category, range }) => `${company} ${category} Geh\xE4lter${range ? ` (${range}/Jahr)` : ""}`,
107
- professionalsEarn: ({ entity, range, count }) => `${entity}-Fachkr\xE4fte verdienen durchschnittlich ${range}/Jahr, basierend auf ${count} Stellenanzeigen.`,
108
- rolesPay: ({ entity, range, count }) => `${entity}-Positionen werden mit durchschnittlich ${range}/Jahr verg\xFCtet, basierend auf ${count} Stellenanzeigen.`,
109
- professionalsInLocationEarn: ({ entity, place, range, count }) => `${entity}-Fachkr\xE4fte in ${place} verdienen durchschnittlich ${range}/Jahr, basierend auf ${count} Stellenanzeigen.`,
110
- seniorityRange: ({ lowLabel, lowAmount, highLabel, highAmount }) => `${lowLabel}-Positionen beginnen bei ${lowAmount}, ${highLabel}-Positionen erreichen ${highAmount}.`,
111
- seniorityRangeWhile: ({ lowLabel, lowAmount, highLabel, highAmount }) => `${lowLabel}-Geh\xE4lter beginnen bei ${lowAmount}, w\xE4hrend ${highLabel}-Positionen ${highAmount} erreichen.`,
112
- compareAcrossTopPaying: ({ count }) => `Vergleichen Sie ${count} ${count === 1 ? "bestzahlendes" : "bestzahlende"} Unternehmen.`,
113
- compareAcrossTop: ({ count }) => `Vergleichen Sie ${count} Top-Unternehmen.`,
114
- boardWideAverage: ({ entity, range }) => `Gesamtdurchschnitt ${entity}: ${range}/Jahr.`,
115
- averageSalaryInCity: ({ place, range, count }) => `Das Durchschnittsgehalt in ${place} betr\xE4gt ${range}/Jahr, basierend auf ${count} Stellen. Gehaltsdaten nach Titel und F\xE4higkeiten durchsuchen.`,
116
- browseLocationsInRegion: ({ count, place }) => `Gehaltsdaten f\xFCr ${count} Standorte in ${place} durchsuchen. Geh\xE4lter nach Titel, F\xE4higkeiten und Unternehmen vergleichen.`,
117
- companyPays: ({ company, range, count }) => `${company} zahlt durchschnittlich ${range}/Jahr, basierend auf ${count} Stellenanzeigen.`,
118
- breakdownAcrossCategories: ({ count }) => `Aufschl\xFCsselung \xFCber ${count} Job-${count === 1 ? "Kategorie" : "Kategorien"}.`,
119
- compareWithSimilar: ({ count }) => `Vergleichen Sie mit ${count} \xE4hnlichen Unternehmen.`,
120
- salaryInfoFor: ({ company, board }) => `Gehaltsinformationen f\xFCr ${company} auf ${board}.`,
121
- categoryRolesAtCompanyPay: ({ category, company, range, count }) => `${category}-Positionen bei ${company} werden mit ${range}/Jahr verg\xFCtet, basierend auf ${count} Stellenanzeigen.`,
122
- categorySalaryDataFor: ({ category, company, board }) => `${category}-Gehaltsdaten f\xFCr ${company} auf ${board}.`
123
- }
124
- };
125
- var LEXICONS = { en: EN, de: DE };
126
- function getSalaryLexicon(locale) {
127
- return locale && LEXICONS[locale] || EN;
128
- }
129
-
130
- // src/format/labels.ts
131
- var EN_LABELS = {
132
- // remoteOption
133
- on_site: "On-site",
134
- hybrid: "Hybrid",
135
- remote: "Remote",
136
- // employmentType
137
- full_time: "Full-time",
138
- part_time: "Part-time",
139
- contract: "Contract",
140
- internship: "Internship",
141
- temporary: "Temporary",
142
- volunteer: "Volunteer",
143
- other: "Other"
144
- };
145
- var DE_LABELS = {
146
- on_site: "Vor Ort",
147
- hybrid: "Hybrid",
148
- remote: "Remote",
149
- full_time: "Vollzeit",
150
- part_time: "Teilzeit",
151
- contract: "Freiberuflich",
152
- internship: "Praktikum",
153
- temporary: "Befristet",
154
- volunteer: "Ehrenamtlich",
155
- other: "Sonstiges"
156
- };
157
- var FR_LABELS = {
158
- on_site: "Sur site",
159
- hybrid: "Hybride",
160
- remote: "T\xE9l\xE9travail",
161
- full_time: "Temps plein",
162
- part_time: "Temps partiel",
163
- contract: "Contrat",
164
- internship: "Stage",
165
- temporary: "Temporaire",
166
- volunteer: "B\xE9n\xE9volat",
167
- other: "Autre"
168
- };
169
- var VOCABULARIES = {
170
- en: EN_LABELS,
171
- de: DE_LABELS,
172
- fr: FR_LABELS
173
- };
174
- var OVERRIDE_KEYS = {
175
- on_site: "onSiteLabel",
176
- hybrid: "hybridLabel",
177
- remote: "remoteLabel",
178
- full_time: "fullTimeLabel",
179
- part_time: "partTimeLabel",
180
- contract: "contractLabel",
181
- internship: "internshipLabel",
182
- temporary: "temporaryLabel",
183
- volunteer: "volunteerLabel",
184
- entry_level: "seniorityEntryLevel",
185
- associate: "seniorityAssociate",
186
- mid_level: "seniorityMidLevel",
187
- senior: "senioritySenior",
188
- lead: "seniorityLead",
189
- principal: "seniorityPrincipal",
190
- director: "seniorityDirector",
191
- executive: "seniorityExecutive"
192
- };
193
- var SENIORITY_KEYS = /* @__PURE__ */ new Set([
194
- "entry_level",
195
- "associate",
196
- "mid_level",
197
- "senior",
198
- "lead",
199
- "principal",
200
- "director",
201
- "executive"
202
- ]);
203
- function storedOverride(value, labels) {
204
- const key = OVERRIDE_KEYS[value];
205
- const override = key ? labels?.jobCardLabels?.[key] : void 0;
206
- return typeof override === "string" && override.trim() !== "" ? override : null;
207
- }
208
- function fieldLabel(locale, value, labels) {
209
- if (!value) return null;
210
- const override = storedOverride(value, labels);
211
- if (override) return override;
212
- if (SENIORITY_KEYS.has(value)) {
213
- return getSalaryLexicon(locale).seniority[value];
214
- }
215
- const vocabulary = VOCABULARIES[locale] ?? EN_LABELS;
216
- return vocabulary[value] ?? EN_LABELS[value] ?? value;
217
- }
218
-
219
- // src/format/ui-copy.ts
220
- var EN2 = {
221
- jobCard: {
222
- featuredLabel: "Featured",
223
- aiRankedLabel: "AI-ranked",
224
- sortNewestLabel: "Most recent",
225
- sortSalaryHighLabel: "Salary: high to low"
226
- },
227
- jobSearch: {
228
- headingJobs: "Jobs",
229
- keywordLabel: "Keyword",
230
- keywordPlaceholder: "Search jobs\u2026",
231
- locationLabel: "Location",
232
- locationPlaceholder: "City or region",
233
- workplacePlaceholder: "Workplace",
234
- anyWorkplaceLabel: "Any workplace",
235
- typePlaceholder: "Type",
236
- anyTypeLabel: "Any type",
237
- sortPlaceholder: "Sort",
238
- loadMoreLabel: "Load more",
239
- noJobsMatchText: "No jobs match \u2014 try clearing a filter."
240
- },
241
- jobDetail: {
242
- categoriesHeading: "Categories",
243
- skillsHeading: "Skills",
244
- additionalDetailsHeading: "Additional details",
245
- customFieldYesLabel: "Yes",
246
- customFieldNoLabel: "No",
247
- locationsLabel: "Locations",
248
- workPermitsLabel: "Work permits",
249
- timezonesLabel: "Timezones",
250
- educationLabel: "Education",
251
- experienceLabel: "Experience",
252
- worldwideLabel: "Worldwide",
253
- noExperienceRequiredLabel: "No experience required",
254
- experienceYears: (years) => `${years}+ years`,
255
- posted: (published) => `Posted ${published}`,
256
- noDescriptionText: "No description provided.",
257
- viewCompanyProfileLabel: "View company profile",
258
- similarJobsHeading: "Similar jobs",
259
- breadcrumbAriaLabel: "Breadcrumb"
260
- },
261
- apply: {
262
- applyButtonText: "Apply for this job",
263
- applyingLabel: "Applying\u2026",
264
- applyOnEmployerSiteLabel: "Apply on employer site",
265
- signInToApplyLabel: "Sign in to apply",
266
- verifyEmailToApplyLabel: "Verify email to apply",
267
- appliedViewApplicationsLabel: "Applied \u2014 view applications",
268
- applicationSubmitError: "Something went wrong. Please try again."
269
- },
270
- alerts: {
271
- jobAlertTitle: "Get job alerts",
272
- jobAlertEmailPlaceholder: "you@example.com",
273
- jobAlertButtonText: "Get alerts",
274
- subscribingLabel: "Subscribing\u2026",
275
- jobAlertSuccessToast: "If this email isn't already subscribed, we've sent a confirmation link \u2014 check your inbox.",
276
- jobAlertErrorToast: "Something went wrong. Please try again.",
277
- sectionAriaLabel: "Job alerts",
278
- emailAriaLabel: "email",
279
- submitAriaLabel: "get job alerts"
280
- },
281
- copyLink: {
282
- copyLinkLabel: "Copy link",
283
- copiedLabel: "Copied",
284
- ariaLabel: "copy link"
285
- },
286
- salary: {
287
- comparisonHeadlineAverage: "Average salary",
288
- perYearSuffix: "/ year",
289
- comparisonPercentile25Label: "25th percentile",
290
- medianLabel: "Median",
291
- comparisonPercentile75Label: "75th percentile",
292
- basedOnLabel: "Based on",
293
- seniorityTableHeaderLevel: "Level",
294
- seniorityTableHeaderAvg: "Average",
295
- boardBaselineLabel: "Board baseline",
296
- seniorityTableHeaderDiff: "vs. board",
297
- faqHeading: "Frequently asked questions"
298
- },
299
- nav: {
300
- home: "Jobs",
301
- companies: "Companies",
302
- pricing: "Pricing",
303
- talent: "Talent",
304
- post: "Post a job",
305
- blog: "Blog"
306
- },
307
- footer: {
308
- forCandidatesHeading: "For Candidates",
309
- forCompaniesHeading: "For Companies",
310
- resourcesHeading: "Resources",
311
- aboutHeading: "About",
312
- websiteLabel: "Website",
313
- aboutLabel: "About",
314
- contactLabel: "Contact us",
315
- locationsLabel: "Locations",
316
- salariesLabel: "Salaries",
317
- sitemapLabel: "Sitemap",
318
- termsOfServiceLabel: "Terms of Service",
319
- privacyPolicyLabel: "Privacy Policy",
320
- cookiePolicyLabel: "Cookie Policy",
321
- impressumLabel: "Impressum",
322
- allRightsReservedText: "All rights reserved.",
323
- copyrightPrefix: "\xA9 {{year}} {{board_name}}.",
324
- poweredByText: "Powered by",
325
- defaultDescription: "Discover the latest roles from {{board_name}}."
326
- },
327
- breadcrumbs: {
328
- home: "Home",
329
- jobs: "Jobs",
330
- locations: "Locations",
331
- salaries: "Salaries",
332
- companies: "Companies",
333
- skills: "Skills",
334
- titles: "Titles",
335
- blog: "Blog",
336
- post: "Post a Job",
337
- pricing: "Pricing",
338
- about: "About",
339
- impressum: "Impressum",
340
- termsOfService: "Terms of Service",
341
- privacyPolicy: "Privacy Policy",
342
- cookiePolicy: "Cookie Policy",
343
- talent: "Talent"
344
- },
345
- pagination: {
346
- ariaLabel: "Pagination",
347
- previousLabel: "Previous",
348
- nextLabel: "Next"
349
- },
350
- blog: {
351
- bylineLabel: "By",
352
- readingTimeLabel: "min read",
353
- searchLabel: "Search",
354
- searchPlaceholder: "Search posts...",
355
- clearButtonLabel: "Clear search",
356
- tagFilterLabel: "Topics",
357
- tagFilterAllLabel: "All",
358
- emptyTitle: "No matching posts",
359
- emptyDescription: "Try adjusting your search or clearing your filters.",
360
- emptyResetLabel: "Clear filters"
361
- },
362
- entity: {
363
- jobSingular: "job",
364
- jobPlural: "jobs",
365
- companySingular: "company",
366
- companyPlural: "companies"
367
- }
368
- };
369
- var DE2 = {
370
- jobCard: {
371
- featuredLabel: "Hervorgehoben",
372
- aiRankedLabel: "KI-sortiert",
373
- sortNewestLabel: "Neueste zuerst",
374
- sortSalaryHighLabel: "Gehalt: absteigend"
375
- },
376
- jobSearch: {
377
- headingJobs: "Jobs",
378
- keywordLabel: "Stichwort",
379
- keywordPlaceholder: "Jobtitel oder -beschreibungen suchen",
380
- locationLabel: "Standort",
381
- locationPlaceholder: "Stadt, Land oder Region",
382
- workplacePlaceholder: "Arbeitsmodell",
383
- anyWorkplaceLabel: "Alle Arbeitsmodelle",
384
- typePlaceholder: "Anstellungsart",
385
- anyTypeLabel: "Alle Anstellungsarten",
386
- sortPlaceholder: "Sortieren",
387
- loadMoreLabel: "Mehr laden",
388
- noJobsMatchText: "Keine passenden Jobs \u2014 setze einen Filter zur\xFCck."
389
- },
390
- jobDetail: {
391
- categoriesHeading: "Kategorien",
392
- skillsHeading: "F\xE4higkeiten",
393
- additionalDetailsHeading: "Weitere Details",
394
- customFieldYesLabel: "Ja",
395
- customFieldNoLabel: "Nein",
396
- locationsLabel: "Standorte",
397
- workPermitsLabel: "Arbeitserlaubnis",
398
- timezonesLabel: "Zeitzonen",
399
- educationLabel: "Ausbildung",
400
- experienceLabel: "Berufserfahrung",
401
- worldwideLabel: "Weltweit",
402
- noExperienceRequiredLabel: "Keine Berufserfahrung erforderlich",
403
- experienceYears: (years) => `${years}+ Jahre`,
404
- posted: (published) => `Ver\xF6ffentlicht ${published}`,
405
- noDescriptionText: "Keine Beschreibung vorhanden.",
406
- viewCompanyProfileLabel: "Unternehmensprofil ansehen",
407
- similarJobsHeading: "\xC4hnliche Jobs",
408
- breadcrumbAriaLabel: "Seitenpfad"
409
- },
410
- apply: {
411
- applyButtonText: "Jetzt bewerben",
412
- applyingLabel: "Wird gesendet \u2026",
413
- applyOnEmployerSiteLabel: "Beim Unternehmen bewerben",
414
- signInToApplyLabel: "Zum Bewerben anmelden",
415
- verifyEmailToApplyLabel: "E-Mail best\xE4tigen, um dich zu bewerben",
416
- appliedViewApplicationsLabel: "Beworben \u2014 Bewerbungen ansehen",
417
- applicationSubmitError: "Etwas ist schiefgelaufen. Bitte versuche es erneut."
418
- },
419
- alerts: {
420
- jobAlertTitle: "Job-Benachrichtigungen erhalten",
421
- jobAlertEmailPlaceholder: "name@beispiel.de",
422
- jobAlertButtonText: "Abonnieren",
423
- subscribingLabel: "Wird abonniert \u2026",
424
- jobAlertSuccessToast: "Falls diese E-Mail noch nicht abonniert ist, haben wir einen Best\xE4tigungslink gesendet \u2014 pr\xFCfe deinen Posteingang.",
425
- jobAlertErrorToast: "Etwas ist schiefgelaufen. Bitte versuche es erneut.",
426
- sectionAriaLabel: "Job-Benachrichtigungen",
427
- emailAriaLabel: "E-Mail",
428
- submitAriaLabel: "Job-Benachrichtigungen erhalten"
429
- },
430
- copyLink: {
431
- copyLinkLabel: "Link kopieren",
432
- copiedLabel: "Kopiert",
433
- ariaLabel: "Link kopieren"
434
- },
435
- salary: {
436
- comparisonHeadlineAverage: "Durchschnittsgehalt",
437
- perYearSuffix: "/ Jahr",
438
- comparisonPercentile25Label: "25. Perzentil",
439
- medianLabel: "Median",
440
- comparisonPercentile75Label: "75. Perzentil",
441
- basedOnLabel: "Basierend auf",
442
- seniorityTableHeaderLevel: "Erfahrungslevel",
443
- seniorityTableHeaderAvg: "Durchschnitt",
444
- boardBaselineLabel: "Board-Durchschnitt",
445
- seniorityTableHeaderDiff: "vs. Board",
446
- faqHeading: "H\xE4ufig gestellte Fragen"
447
- },
448
- nav: {
449
- home: "Jobs",
450
- companies: "Unternehmen",
451
- pricing: "Preise",
452
- talent: "Talente",
453
- post: "Job ver\xF6ffentlichen",
454
- blog: "Blog"
455
- },
456
- footer: {
457
- forCandidatesHeading: "F\xFCr Kandidaten",
458
- forCompaniesHeading: "F\xFCr Unternehmen",
459
- resourcesHeading: "Ressourcen",
460
- aboutHeading: "\xDCber uns",
461
- websiteLabel: "Website",
462
- aboutLabel: "\xDCber uns",
463
- contactLabel: "Kontakt",
464
- locationsLabel: "Standorte",
465
- salariesLabel: "Geh\xE4lter",
466
- sitemapLabel: "Sitemap",
467
- termsOfServiceLabel: "Nutzungsbedingungen",
468
- privacyPolicyLabel: "Datenschutzerkl\xE4rung",
469
- cookiePolicyLabel: "Cookie-Richtlinie",
470
- impressumLabel: "Impressum",
471
- allRightsReservedText: "Alle Rechte vorbehalten.",
472
- copyrightPrefix: "\xA9 {{year}} {{board_name}}.",
473
- poweredByText: "Bereitgestellt von",
474
- defaultDescription: "Entdecke die neuesten Stellen von {{board_name}}."
475
- },
476
- breadcrumbs: {
477
- home: "Startseite",
478
- jobs: "Jobs",
479
- locations: "Standorte",
480
- salaries: "Geh\xE4lter",
481
- companies: "Unternehmen",
482
- skills: "F\xE4higkeiten",
483
- titles: "Berufsbezeichnungen",
484
- blog: "Blog",
485
- post: "Job ver\xF6ffentlichen",
486
- pricing: "Preise",
487
- about: "\xDCber uns",
488
- impressum: "Impressum",
489
- termsOfService: "Nutzungsbedingungen",
490
- privacyPolicy: "Datenschutzerkl\xE4rung",
491
- cookiePolicy: "Cookie-Richtlinie",
492
- talent: "Talente"
493
- },
494
- pagination: {
495
- ariaLabel: "Seitennummerierung",
496
- previousLabel: "Zur\xFCck",
497
- nextLabel: "Weiter"
498
- },
499
- blog: {
500
- bylineLabel: "Von",
501
- readingTimeLabel: "Minuten Lesezeit",
502
- searchLabel: "Suche",
503
- searchPlaceholder: "Artikel suchen...",
504
- clearButtonLabel: "Suche leeren",
505
- tagFilterLabel: "Themen",
506
- tagFilterAllLabel: "Alle",
507
- emptyTitle: "Keine passenden Artikel gefunden",
508
- emptyDescription: "Versuche, deine Suche anzupassen oder die Filter zur\xFCckzusetzen.",
509
- emptyResetLabel: "Filter zur\xFCcksetzen"
510
- },
511
- entity: {
512
- jobSingular: "Job",
513
- jobPlural: "Jobs",
514
- companySingular: "Unternehmen",
515
- companyPlural: "Unternehmen"
516
- }
517
- };
518
- var FR = {
519
- jobCard: {
520
- featuredLabel: "\xC0 la une",
521
- aiRankedLabel: "Classement IA",
522
- sortNewestLabel: "Plus r\xE9centes",
523
- sortSalaryHighLabel: "Salaire : d\xE9croissant"
524
- },
525
- jobSearch: {
526
- headingJobs: "Offres d'emploi",
527
- keywordLabel: "Mot-cl\xE9",
528
- keywordPlaceholder: "Rechercher une offre\u2026",
529
- locationLabel: "Lieu",
530
- locationPlaceholder: "Ville ou r\xE9gion",
531
- workplacePlaceholder: "Mode de travail",
532
- anyWorkplaceLabel: "Tous les modes de travail",
533
- typePlaceholder: "Type de contrat",
534
- anyTypeLabel: "Tous les types",
535
- sortPlaceholder: "Trier",
536
- loadMoreLabel: "Voir plus",
537
- noJobsMatchText: "Aucune offre ne correspond \u2014 essayez de retirer un filtre."
538
- },
539
- jobDetail: {
540
- categoriesHeading: "Cat\xE9gories",
541
- skillsHeading: "Comp\xE9tences",
542
- additionalDetailsHeading: "Informations compl\xE9mentaires",
543
- customFieldYesLabel: "Oui",
544
- customFieldNoLabel: "Non",
545
- locationsLabel: "Lieux",
546
- workPermitsLabel: "Permis de travail",
547
- timezonesLabel: "Fuseaux horaires",
548
- educationLabel: "Formation",
549
- experienceLabel: "Exp\xE9rience",
550
- worldwideLabel: "Monde entier",
551
- noExperienceRequiredLabel: "Aucune exp\xE9rience requise",
552
- experienceYears: (years) => `${years}+ ans`,
553
- posted: (published) => `Publi\xE9e ${published}`,
554
- noDescriptionText: "Aucune description fournie.",
555
- viewCompanyProfileLabel: "Voir le profil de l'entreprise",
556
- similarJobsHeading: "Offres similaires",
557
- breadcrumbAriaLabel: "Fil d'Ariane"
558
- },
559
- apply: {
560
- applyButtonText: "Postuler \xE0 cette offre",
561
- applyingLabel: "Envoi en cours\u2026",
562
- applyOnEmployerSiteLabel: "Postuler sur le site de l'employeur",
563
- signInToApplyLabel: "Connectez-vous pour postuler",
564
- verifyEmailToApplyLabel: "V\xE9rifiez votre e-mail pour postuler",
565
- appliedViewApplicationsLabel: "Candidature envoy\xE9e \u2014 voir mes candidatures",
566
- applicationSubmitError: "Une erreur est survenue. Veuillez r\xE9essayer."
567
- },
568
- alerts: {
569
- jobAlertTitle: "Recevoir des alertes emploi",
570
- jobAlertEmailPlaceholder: "vous@exemple.fr",
571
- jobAlertButtonText: "Activer les alertes",
572
- subscribingLabel: "Abonnement en cours\u2026",
573
- jobAlertSuccessToast: "Si cet e-mail n'est pas d\xE9j\xE0 abonn\xE9, nous avons envoy\xE9 un lien de confirmation \u2014 v\xE9rifiez votre bo\xEEte de r\xE9ception.",
574
- jobAlertErrorToast: "Une erreur est survenue. Veuillez r\xE9essayer.",
575
- sectionAriaLabel: "Alertes emploi",
576
- emailAriaLabel: "e-mail",
577
- submitAriaLabel: "recevoir des alertes emploi"
578
- },
579
- copyLink: {
580
- copyLinkLabel: "Copier le lien",
581
- copiedLabel: "Copi\xE9",
582
- ariaLabel: "copier le lien"
583
- },
584
- salary: {
585
- comparisonHeadlineAverage: "Salaire moyen",
586
- perYearSuffix: "/ an",
587
- comparisonPercentile25Label: "25e percentile",
588
- medianLabel: "M\xE9diane",
589
- comparisonPercentile75Label: "75e percentile",
590
- basedOnLabel: "Bas\xE9 sur",
591
- seniorityTableHeaderLevel: "Niveau",
592
- seniorityTableHeaderAvg: "Moyenne",
593
- boardBaselineLabel: "R\xE9f\xE9rence du site",
594
- seniorityTableHeaderDiff: "vs site",
595
- faqHeading: "Questions fr\xE9quentes"
596
- },
597
- nav: {
598
- home: "Offres",
599
- companies: "Entreprises",
600
- pricing: "Tarifs",
601
- talent: "Talents",
602
- post: "Publier une offre",
603
- blog: "Blog"
604
- },
605
- footer: {
606
- forCandidatesHeading: "Pour les candidats",
607
- forCompaniesHeading: "Pour les entreprises",
608
- resourcesHeading: "Ressources",
609
- aboutHeading: "\xC0 propos",
610
- websiteLabel: "Site web",
611
- aboutLabel: "\xC0 propos",
612
- contactLabel: "Nous contacter",
613
- locationsLabel: "Lieux",
614
- salariesLabel: "Salaires",
615
- sitemapLabel: "Plan du site",
616
- termsOfServiceLabel: "Conditions d'utilisation",
617
- privacyPolicyLabel: "Politique de confidentialit\xE9",
618
- cookiePolicyLabel: "Politique de cookies",
619
- impressumLabel: "Mentions l\xE9gales",
620
- allRightsReservedText: "Tous droits r\xE9serv\xE9s.",
621
- copyrightPrefix: "\xA9 {{year}} {{board_name}}.",
622
- poweredByText: "Propuls\xE9 par",
623
- defaultDescription: "D\xE9couvrez les derni\xE8res offres de {{board_name}}."
624
- },
625
- breadcrumbs: {
626
- home: "Accueil",
627
- jobs: "Offres",
628
- locations: "Lieux",
629
- salaries: "Salaires",
630
- companies: "Entreprises",
631
- skills: "Comp\xE9tences",
632
- titles: "Intitul\xE9s de poste",
633
- blog: "Blog",
634
- post: "Publier une offre",
635
- pricing: "Tarifs",
636
- about: "\xC0 propos",
637
- impressum: "Mentions l\xE9gales",
638
- termsOfService: "Conditions d'utilisation",
639
- privacyPolicy: "Politique de confidentialit\xE9",
640
- cookiePolicy: "Politique de cookies",
641
- talent: "Talents"
642
- },
643
- pagination: {
644
- ariaLabel: "Pagination",
645
- previousLabel: "Pr\xE9c\xE9dent",
646
- nextLabel: "Suivant"
647
- },
648
- blog: {
649
- bylineLabel: "Par",
650
- readingTimeLabel: "min de lecture",
651
- searchLabel: "Recherche",
652
- searchPlaceholder: "Rechercher un article...",
653
- clearButtonLabel: "Effacer la recherche",
654
- tagFilterLabel: "Th\xE8mes",
655
- tagFilterAllLabel: "Tous",
656
- emptyTitle: "Aucun article correspondant",
657
- emptyDescription: "Essayez de modifier votre recherche ou de r\xE9initialiser les filtres.",
658
- emptyResetLabel: "R\xE9initialiser les filtres"
659
- },
660
- entity: {
661
- jobSingular: "offre",
662
- jobPlural: "offres",
663
- companySingular: "entreprise",
664
- companyPlural: "entreprises"
665
- }
666
- };
667
- var CATALOGS = { en: EN2, de: DE2, fr: FR };
668
- function mergeGroup(group, overrides) {
669
- if (!overrides) return group;
670
- const out = { ...group };
671
- for (const [key, value] of Object.entries(group)) {
672
- if (typeof value !== "string") continue;
673
- const override = overrides[key];
674
- if (typeof override === "string" && override.trim() !== "") {
675
- out[key] = override;
676
- }
677
- }
678
- return out;
679
- }
680
- var GROUP_OVERRIDE_SOURCE = {
681
- jobCard: "jobCardLabels",
682
- jobSearch: "jobSearchLabels",
683
- jobDetail: "jobCardLabels",
684
- apply: "jobCardLabels",
685
- alerts: "jobCardLabels",
686
- copyLink: "jobCardLabels",
687
- salary: "salaryLabels",
688
- nav: "navLabels",
689
- footer: "footerLabels",
690
- breadcrumbs: "breadcrumbsLabels",
691
- pagination: "globalPaginationLabels",
692
- blog: "blogSharedLabels",
693
- entity: "entityLabels"
694
- };
695
- function uiCopy(language, labels) {
696
- const catalog = language && CATALOGS[language] || EN2;
697
- if (!labels) return catalog;
698
- const resolved = {};
699
- for (const [group, source] of Object.entries(GROUP_OVERRIDE_SOURCE)) {
700
- resolved[group] = mergeGroup(catalog[group], labels[source]);
701
- }
702
- return resolved;
703
- }
704
-
705
- // src/filters/index.ts
706
33
  var REMOTE_OPTIONS = [
707
34
  "on_site",
708
35
  "hybrid",
@@ -731,22 +58,6 @@ var JOB_SORTS = [
731
58
  "salary_high"
732
59
  ];
733
60
  var DEFAULT_SORT = "relevance";
734
- function seniorityLabels(locale, labels) {
735
- if (!labels?.jobCardLabels) return getSalaryLexicon(locale).seniority;
736
- const out = {};
737
- for (const seniority of SENIORITIES) {
738
- out[seniority] = fieldLabel(locale, seniority, labels) ?? seniority;
739
- }
740
- return out;
741
- }
742
- function sortLabels(locale, labels) {
743
- const copy = uiCopy(locale, labels).jobCard;
744
- return {
745
- relevance: copy.aiRankedLabel,
746
- newest: copy.sortNewestLabel,
747
- salary_high: copy.sortSalaryHighLabel
748
- };
749
- }
750
61
  var COMPANY_SLUG_MAX = 10;
751
62
  var SENIORITY_LOOKUP = new Set(SENIORITIES);
752
63
  function parseSeniority(raw) {
@@ -755,7 +66,7 @@ function parseSeniority(raw) {
755
66
  const seen = /* @__PURE__ */ new Set();
756
67
  for (const value of values) {
757
68
  if (typeof value !== "string") continue;
758
- const normalized = value.trim().toLowerCase();
69
+ const normalized = value.trim().toLowerCase().normalize("NFC");
759
70
  if (!normalized || seen.has(normalized)) continue;
760
71
  if (!SENIORITY_LOOKUP.has(normalized)) continue;
761
72
  seen.add(normalized);
@@ -769,7 +80,7 @@ function parseCompany(raw) {
769
80
  const seen = /* @__PURE__ */ new Set();
770
81
  for (const value of values) {
771
82
  if (typeof value !== "string") continue;
772
- const normalized = value.trim().toLowerCase();
83
+ const normalized = value.trim().toLowerCase().normalize("NFC");
773
84
  if (!normalized || seen.has(normalized)) continue;
774
85
  seen.add(normalized);
775
86
  result.push(normalized);