@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.
- package/CHANGELOG.md +406 -0
- package/README.md +6 -2
- package/dist/{_spec-nkWAraS0.d.mts → _spec-GVe6WAfT.d.mts} +68 -59
- package/dist/{_spec-nkWAraS0.d.ts → _spec-GVe6WAfT.d.ts} +68 -59
- package/dist/bin.mjs +7 -2
- package/dist/{blog-iV9XEIGf.d.ts → blog-BsmKizpd.d.ts} +1 -1
- package/dist/{blog-DGBHmExV.d.mts → blog-Cf64mI8A.d.mts} +1 -1
- package/dist/{board-BJbXd_9_.d.mts → board-DUhgiacm.d.ts} +7 -6
- package/dist/{board-JhdUWIoq.d.ts → board-GGWJ4coe.d.mts} +7 -6
- package/dist/breadcrumbs-DFKr0HzU.d.mts +372 -0
- package/dist/breadcrumbs-DiccJhk4.d.ts +372 -0
- package/dist/chunk-BGKNXG4H.mjs +146 -0
- package/dist/{chunk-NXY3OWGF.mjs → chunk-T2KC6XGV.mjs} +1 -1
- package/dist/{chunk-STE77MAT.mjs → chunk-YEAQ3JEI.mjs} +143 -134
- package/dist/doctor.js +1 -1
- package/dist/doctor.mjs +1 -1
- package/dist/filters.d.mts +25 -20
- package/dist/filters.d.ts +25 -20
- package/dist/filters.js +3 -692
- package/dist/filters.mjs +3 -29
- package/dist/format.d.mts +57 -231
- package/dist/format.d.ts +57 -231
- package/dist/format.js +327 -968
- package/dist/format.mjs +207 -264
- package/dist/go.js +11 -1
- package/dist/go.mjs +1 -1
- package/dist/index.d.mts +23 -76
- package/dist/index.d.ts +23 -76
- package/dist/index.js +11 -36
- package/dist/index.mjs +11 -36
- package/dist/{jobs-BiEvL9d7.d.ts → jobs-BuLpV8iy.d.mts} +4 -4
- package/dist/{jobs-lVvKCBCU.d.mts → jobs-QrbXOYB9.d.ts} +4 -4
- package/dist/paths.d.mts +89 -1
- package/dist/paths.d.ts +89 -1
- package/dist/paths.js +62 -14
- package/dist/paths.mjs +11 -3
- package/dist/route-contract.js +23 -13
- package/dist/route-contract.mjs +2 -2
- package/dist/{search-CyRvVMUp.d.ts → search-Cr4noJJZ.d.mts} +14 -3
- package/dist/{search-CCyFWPi3.d.mts → search-DdsniXQv.d.ts} +14 -3
- package/dist/seo.d.mts +30 -29
- package/dist/seo.d.ts +30 -29
- package/dist/seo.js +197 -718
- package/dist/seo.mjs +26 -24
- package/dist/server.d.mts +5 -5
- package/dist/server.d.ts +5 -5
- package/dist/sitemap.d.mts +5 -5
- package/dist/sitemap.d.ts +5 -5
- package/dist/sitemap.js +25 -14
- package/dist/sitemap.mjs +3 -2
- package/dist/skills.js +1 -1
- package/dist/skills.mjs +1 -1
- package/dist/suggest.d.mts +2 -2
- package/dist/suggest.d.ts +2 -2
- package/dist/suggest.js +17 -3
- package/dist/suggest.mjs +17 -3
- package/dist/well-known.js +23 -13
- package/dist/well-known.mjs +2 -2
- package/package.json +2 -4
- package/skills/cavuno-board-applications/SKILL.md +4 -1
- package/skills/cavuno-board-filters/SKILL.md +11 -12
- package/skills/cavuno-board-format/SKILL.md +68 -56
- package/skills/cavuno-board-i18n/SKILL.md +102 -21
- package/skills/cavuno-board-search-suggestions/SKILL.md +8 -3
- package/skills/cavuno-board-seo/BLOG.md +4 -1
- package/skills/cavuno-board-seo/JOB_AND_BREADCRUMBS.md +5 -2
- package/skills/cavuno-board-seo/LISTING.md +35 -12
- package/skills/cavuno-board-seo/SALARY.md +83 -18
- package/skills/cavuno-board-seo/SKILL.md +3 -2
- package/skills/manifest.json +3 -3
- package/dist/breadcrumbs-1hMjcsqA.d.mts +0 -171
- package/dist/breadcrumbs-DexU07TT.d.ts +0 -171
- package/dist/chunk-IJCJ26SQ.mjs +0 -596
- package/dist/chunk-L7ZOYWHW.mjs +0 -98
- package/dist/chunk-LUGJWOT7.mjs +0 -96
- package/dist/ui-copy-CCkz6CVF.d.mts +0 -230
- package/dist/ui-copy-CCkz6CVF.d.ts +0 -230
|
@@ -1,51 +1,83 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
BOARD_PATHS,
|
|
3
|
+
jobsCategoryPath,
|
|
4
|
+
jobsLocationCategoryPath,
|
|
5
|
+
jobsLocationPath
|
|
6
|
+
} from "./chunk-BGKNXG4H.mjs";
|
|
5
7
|
|
|
6
|
-
// src/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (cached) return cached;
|
|
11
|
-
const formatter = new Intl.NumberFormat(language, {
|
|
12
|
-
style: "currency",
|
|
13
|
-
currency: "USD",
|
|
14
|
-
notation: "compact",
|
|
15
|
-
compactDisplay: "short",
|
|
16
|
-
minimumFractionDigits: 0,
|
|
17
|
-
maximumFractionDigits: 1
|
|
18
|
-
});
|
|
19
|
-
compactCurrencyCache.set(language, formatter);
|
|
20
|
-
return formatter;
|
|
21
|
-
}
|
|
22
|
-
function formatUsd(locale, value) {
|
|
8
|
+
// src/format/locale.ts
|
|
9
|
+
function normalizeLocale(language) {
|
|
10
|
+
const trimmed = language.trim();
|
|
11
|
+
if (!trimmed) return null;
|
|
23
12
|
try {
|
|
24
|
-
|
|
13
|
+
const candidate = trimmed.replace(/_/g, "-");
|
|
14
|
+
const [canonical] = Intl.getCanonicalLocales(candidate);
|
|
15
|
+
if (!canonical) return null;
|
|
16
|
+
const [supported] = Intl.NumberFormat.supportedLocalesOf([canonical]);
|
|
17
|
+
return supported ?? null;
|
|
25
18
|
} catch {
|
|
26
|
-
|
|
27
|
-
const millions = value / 1e6;
|
|
28
|
-
return `$${millions % 1 === 0 ? millions : millions.toFixed(1)}M`;
|
|
29
|
-
}
|
|
30
|
-
if (value >= 1e3) {
|
|
31
|
-
const thousands = value / 1e3;
|
|
32
|
-
return `$${thousands % 1 === 0 ? thousands : thousands.toFixed(1)}k`;
|
|
33
|
-
}
|
|
34
|
-
return `$${value}`;
|
|
19
|
+
return null;
|
|
35
20
|
}
|
|
36
21
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
|
|
22
|
+
|
|
23
|
+
// src/seo/salary.ts
|
|
24
|
+
var currencyFormatterCache = /* @__PURE__ */ new Map();
|
|
25
|
+
function notationForMagnitude(...values) {
|
|
26
|
+
let anyFinite = false;
|
|
27
|
+
for (const v of values) {
|
|
28
|
+
if (v == null || !Number.isFinite(v)) continue;
|
|
29
|
+
anyFinite = true;
|
|
30
|
+
if (Math.abs(v) >= 1e3) return "compact";
|
|
43
31
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
32
|
+
return anyFinite ? "standard" : "compact";
|
|
33
|
+
}
|
|
34
|
+
function getCurrencyFormatter(language, currencyCode, notation) {
|
|
35
|
+
const key = `${language}:${currencyCode}:${notation}`;
|
|
36
|
+
const cached = currencyFormatterCache.get(key);
|
|
37
|
+
if (cached !== void 0) return cached;
|
|
38
|
+
let formatter;
|
|
39
|
+
try {
|
|
40
|
+
const options = {
|
|
41
|
+
style: "currency",
|
|
42
|
+
currency: currencyCode,
|
|
43
|
+
notation
|
|
44
|
+
};
|
|
45
|
+
if (notation === "compact") {
|
|
46
|
+
options.compactDisplay = "short";
|
|
47
|
+
options.minimumFractionDigits = 0;
|
|
48
|
+
options.maximumFractionDigits = 1;
|
|
49
|
+
}
|
|
50
|
+
formatter = new Intl.NumberFormat(language, options);
|
|
51
|
+
} catch {
|
|
52
|
+
formatter = null;
|
|
47
53
|
}
|
|
48
|
-
|
|
54
|
+
currencyFormatterCache.set(key, formatter);
|
|
55
|
+
return formatter;
|
|
56
|
+
}
|
|
57
|
+
function formatSalaryStat(locale, value, currency, notation) {
|
|
58
|
+
if (!Number.isFinite(value)) return null;
|
|
59
|
+
const currencyCode = currency?.trim().toUpperCase() || null;
|
|
60
|
+
if (!currencyCode) return null;
|
|
61
|
+
const normalized = normalizeLocale(locale);
|
|
62
|
+
if (!normalized) return null;
|
|
63
|
+
const resolved = notation ?? notationForMagnitude(value);
|
|
64
|
+
const formatter = getCurrencyFormatter(normalized, currencyCode, resolved);
|
|
65
|
+
if (!formatter) return null;
|
|
66
|
+
return formatter.format(value);
|
|
67
|
+
}
|
|
68
|
+
function formatSalaryStatRange(locale, min, max, currency, notation) {
|
|
69
|
+
if (!Number.isFinite(min) || !Number.isFinite(max)) return null;
|
|
70
|
+
const currencyCode = currency?.trim().toUpperCase() || null;
|
|
71
|
+
if (!currencyCode) return null;
|
|
72
|
+
const normalized = normalizeLocale(locale);
|
|
73
|
+
if (!normalized) return null;
|
|
74
|
+
const resolved = notation ?? notationForMagnitude(min, max);
|
|
75
|
+
const formatter = getCurrencyFormatter(normalized, currencyCode, resolved);
|
|
76
|
+
if (!formatter) return null;
|
|
77
|
+
const low = Math.min(min, max);
|
|
78
|
+
const high = Math.max(min, max);
|
|
79
|
+
if (low === high) return formatter.format(low);
|
|
80
|
+
return formatter.formatRange(low, high);
|
|
49
81
|
}
|
|
50
82
|
var SENIORITY_ORDER = [
|
|
51
83
|
"entry_level",
|
|
@@ -75,7 +107,7 @@ var yearly = {
|
|
|
75
107
|
function distribution(name, currency, minValue, maxValue, stats = {}) {
|
|
76
108
|
return {
|
|
77
109
|
"@type": "MonetaryAmountDistribution",
|
|
78
|
-
name,
|
|
110
|
+
...name !== void 0 ? { name } : {},
|
|
79
111
|
currency,
|
|
80
112
|
minValue,
|
|
81
113
|
maxValue,
|
|
@@ -83,15 +115,19 @@ function distribution(name, currency, minValue, maxValue, stats = {}) {
|
|
|
83
115
|
...yearly
|
|
84
116
|
};
|
|
85
117
|
}
|
|
86
|
-
function seniorityDistributions(
|
|
87
|
-
return rows.map(
|
|
88
|
-
|
|
89
|
-
|
|
118
|
+
function seniorityDistributions(rows, currency, entity, options) {
|
|
119
|
+
return rows.map((row) => {
|
|
120
|
+
const name = options?.seniorityName?.({
|
|
121
|
+
seniority: row.seniority,
|
|
122
|
+
entity
|
|
123
|
+
});
|
|
124
|
+
return distribution(
|
|
125
|
+
name,
|
|
90
126
|
currency,
|
|
91
127
|
row.avgSalaryMin,
|
|
92
128
|
row.avgSalaryMax
|
|
93
|
-
)
|
|
94
|
-
);
|
|
129
|
+
);
|
|
130
|
+
});
|
|
95
131
|
}
|
|
96
132
|
function salaryEnvelope(type, name, extra, estimatedSalary) {
|
|
97
133
|
return {
|
|
@@ -102,17 +138,27 @@ function salaryEnvelope(type, name, extra, estimatedSalary) {
|
|
|
102
138
|
estimatedSalary
|
|
103
139
|
};
|
|
104
140
|
}
|
|
105
|
-
function buildSalaryFaq(locale, label, overall) {
|
|
141
|
+
function buildSalaryFaq(locale, label, overall, currency) {
|
|
106
142
|
if (!overall) return [];
|
|
107
|
-
const range =
|
|
143
|
+
const range = formatSalaryStatRange(
|
|
144
|
+
locale,
|
|
145
|
+
overall.avgMin,
|
|
146
|
+
overall.avgMax,
|
|
147
|
+
currency
|
|
148
|
+
);
|
|
108
149
|
return [
|
|
109
150
|
{
|
|
110
|
-
|
|
111
|
-
|
|
151
|
+
kind: "average",
|
|
152
|
+
label,
|
|
153
|
+
range,
|
|
154
|
+
avgMin: overall.avgMin,
|
|
155
|
+
avgMax: overall.avgMax,
|
|
156
|
+
currency,
|
|
157
|
+
jobCount: overall.jobCount
|
|
112
158
|
},
|
|
113
159
|
{
|
|
114
|
-
|
|
115
|
-
|
|
160
|
+
kind: "methodology",
|
|
161
|
+
label
|
|
116
162
|
}
|
|
117
163
|
];
|
|
118
164
|
}
|
|
@@ -142,11 +188,11 @@ function faqJsonLd(faqs) {
|
|
|
142
188
|
}))
|
|
143
189
|
};
|
|
144
190
|
}
|
|
145
|
-
function titleSalaryJsonLd(
|
|
191
|
+
function titleSalaryJsonLd(d, options) {
|
|
146
192
|
if (!d.overallSalary) return null;
|
|
147
193
|
return salaryEnvelope("Occupation", d.categoryName, {}, [
|
|
148
194
|
distribution(
|
|
149
|
-
|
|
195
|
+
d.categoryName,
|
|
150
196
|
d.currency,
|
|
151
197
|
d.overallSalary.avgMin,
|
|
152
198
|
d.overallSalary.avgMax,
|
|
@@ -156,10 +202,10 @@ function titleSalaryJsonLd(locale, d) {
|
|
|
156
202
|
}
|
|
157
203
|
),
|
|
158
204
|
...seniorityDistributions(
|
|
159
|
-
locale,
|
|
160
205
|
d.bySeniority,
|
|
161
206
|
d.currency,
|
|
162
|
-
|
|
207
|
+
d.categoryName,
|
|
208
|
+
options
|
|
163
209
|
)
|
|
164
210
|
]);
|
|
165
211
|
}
|
|
@@ -167,7 +213,7 @@ function skillSalaryJsonLd(d) {
|
|
|
167
213
|
if (!d.overallSalary) return null;
|
|
168
214
|
return salaryEnvelope("Occupation", d.skillName, {}, [
|
|
169
215
|
distribution(
|
|
170
|
-
|
|
216
|
+
d.skillName,
|
|
171
217
|
d.currency,
|
|
172
218
|
d.overallSalary.avgMin,
|
|
173
219
|
d.overallSalary.avgMax,
|
|
@@ -179,42 +225,22 @@ function skillSalaryJsonLd(d) {
|
|
|
179
225
|
)
|
|
180
226
|
]);
|
|
181
227
|
}
|
|
182
|
-
function locationSalaryJsonLd(d) {
|
|
228
|
+
function locationSalaryJsonLd(d, options) {
|
|
229
|
+
if (!options?.occupationUrl) return null;
|
|
183
230
|
const isCity = d.adminLevel === "city" || d.adminLevel === "locality";
|
|
184
|
-
if (!isCity
|
|
185
|
-
return
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
"@type": "City",
|
|
191
|
-
name: d.placeName,
|
|
192
|
-
address: { "@type": "PostalAddress", addressCountry: d.countryCode }
|
|
193
|
-
}
|
|
194
|
-
},
|
|
195
|
-
[
|
|
196
|
-
distribution(
|
|
197
|
-
`Average salary in ${d.placeName}`,
|
|
198
|
-
d.currency,
|
|
199
|
-
d.overallSalary.avgMin,
|
|
200
|
-
d.overallSalary.avgMax,
|
|
201
|
-
{
|
|
202
|
-
median: Math.round(
|
|
203
|
-
(d.overallSalary.medianMin + d.overallSalary.medianMax) / 2
|
|
204
|
-
),
|
|
205
|
-
// Hosted includes these unconditionally, nulls and all.
|
|
206
|
-
percentile25: d.overallSalary.p25Min,
|
|
207
|
-
percentile75: d.overallSalary.p75Max
|
|
208
|
-
}
|
|
209
|
-
)
|
|
210
|
-
]
|
|
231
|
+
if (!isCity) return null;
|
|
232
|
+
return itemListJsonLd(
|
|
233
|
+
d.topCategories.map((c) => ({
|
|
234
|
+
name: c.categoryName,
|
|
235
|
+
url: options.occupationUrl(c)
|
|
236
|
+
}))
|
|
211
237
|
);
|
|
212
238
|
}
|
|
213
|
-
function crossAxisSalaryJsonLd(
|
|
239
|
+
function crossAxisSalaryJsonLd(args, options) {
|
|
214
240
|
if (!args.overall) return null;
|
|
215
241
|
return salaryEnvelope(
|
|
216
242
|
"Occupation",
|
|
217
|
-
|
|
243
|
+
args.name,
|
|
218
244
|
{
|
|
219
245
|
occupationLocation: {
|
|
220
246
|
"@type": "AdministrativeArea",
|
|
@@ -227,7 +253,7 @@ function crossAxisSalaryJsonLd(locale, args) {
|
|
|
227
253
|
},
|
|
228
254
|
[
|
|
229
255
|
distribution(
|
|
230
|
-
|
|
256
|
+
args.name,
|
|
231
257
|
args.currency,
|
|
232
258
|
args.overall.avgMin,
|
|
233
259
|
args.overall.avgMax,
|
|
@@ -237,56 +263,35 @@ function crossAxisSalaryJsonLd(locale, args) {
|
|
|
237
263
|
}
|
|
238
264
|
),
|
|
239
265
|
...seniorityDistributions(
|
|
240
|
-
locale,
|
|
241
266
|
args.bySeniority,
|
|
242
267
|
args.currency,
|
|
243
|
-
|
|
268
|
+
args.name,
|
|
269
|
+
options
|
|
244
270
|
)
|
|
245
271
|
]
|
|
246
272
|
);
|
|
247
273
|
}
|
|
248
|
-
function companySalaryJsonLd(
|
|
249
|
-
if (!
|
|
250
|
-
return
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
hiringOrganization: { "@type": "Organization", name: d.companyName }
|
|
256
|
-
},
|
|
257
|
-
[
|
|
258
|
-
distribution(
|
|
259
|
-
"base",
|
|
260
|
-
d.currency,
|
|
261
|
-
d.overallSalary.avgMin,
|
|
262
|
-
d.overallSalary.avgMax,
|
|
263
|
-
{
|
|
264
|
-
...d.boardMedianMin && d.boardMedianMax ? { median: Math.round((d.boardMedianMin + d.boardMedianMax) / 2) } : {},
|
|
265
|
-
...d.boardP25Min ? { percentile25: d.boardP25Min } : {},
|
|
266
|
-
...d.boardP75Max ? { percentile75: d.boardP75Max } : {}
|
|
267
|
-
}
|
|
268
|
-
),
|
|
269
|
-
...seniorityDistributions(
|
|
270
|
-
locale,
|
|
271
|
-
d.bySeniority,
|
|
272
|
-
d.currency,
|
|
273
|
-
(label) => `${label} salary`
|
|
274
|
-
)
|
|
275
|
-
]
|
|
274
|
+
function companySalaryJsonLd(d, options) {
|
|
275
|
+
if (!options?.occupationUrl) return null;
|
|
276
|
+
return itemListJsonLd(
|
|
277
|
+
d.byCategory.map((c) => ({
|
|
278
|
+
name: c.categoryName,
|
|
279
|
+
url: options.occupationUrl(c)
|
|
280
|
+
}))
|
|
276
281
|
);
|
|
277
282
|
}
|
|
278
|
-
function companyCategorySalaryJsonLd(
|
|
283
|
+
function companyCategorySalaryJsonLd(d, options) {
|
|
279
284
|
if (!d.overallSalary) return null;
|
|
280
285
|
return salaryEnvelope(
|
|
281
286
|
"Occupation",
|
|
282
|
-
|
|
287
|
+
d.categoryName,
|
|
283
288
|
{
|
|
284
289
|
occupationalCategory: d.categoryName,
|
|
285
290
|
hiringOrganization: { "@type": "Organization", name: d.companyName }
|
|
286
291
|
},
|
|
287
292
|
[
|
|
288
293
|
distribution(
|
|
289
|
-
|
|
294
|
+
d.categoryName,
|
|
290
295
|
d.currency,
|
|
291
296
|
d.overallSalary.avgMin,
|
|
292
297
|
d.overallSalary.avgMax,
|
|
@@ -296,10 +301,10 @@ function companyCategorySalaryJsonLd(locale, d) {
|
|
|
296
301
|
}
|
|
297
302
|
),
|
|
298
303
|
...seniorityDistributions(
|
|
299
|
-
locale,
|
|
300
304
|
d.bySeniority,
|
|
301
305
|
d.currency,
|
|
302
|
-
|
|
306
|
+
d.categoryName,
|
|
307
|
+
options
|
|
303
308
|
)
|
|
304
309
|
]
|
|
305
310
|
);
|
|
@@ -799,32 +804,36 @@ function resolveBreadcrumbHref(href, origin) {
|
|
|
799
804
|
function isAbsoluteUrl(href) {
|
|
800
805
|
return /^https?:\/\//i.test(href);
|
|
801
806
|
}
|
|
802
|
-
function buildJobBreadcrumbs(job
|
|
803
|
-
const copy = uiCopy(language, labels).breadcrumbs;
|
|
807
|
+
function buildJobBreadcrumbs(job) {
|
|
804
808
|
const crumbs = [
|
|
805
|
-
{
|
|
806
|
-
{
|
|
809
|
+
{ kind: "home", path: BOARD_PATHS.home },
|
|
810
|
+
{ kind: "jobs", path: BOARD_PATHS.jobs }
|
|
807
811
|
];
|
|
808
812
|
let lastPlaceSlug = null;
|
|
809
813
|
for (const place of job.placeHierarchy) {
|
|
810
814
|
lastPlaceSlug = place.slug;
|
|
811
|
-
crumbs.push({
|
|
815
|
+
crumbs.push({
|
|
816
|
+
kind: "place",
|
|
817
|
+
name: place.name,
|
|
818
|
+
path: jobsLocationPath(place.slug)
|
|
819
|
+
});
|
|
812
820
|
}
|
|
813
821
|
const primaryCategory = job.categories[0];
|
|
814
822
|
if (primaryCategory) {
|
|
815
823
|
crumbs.push({
|
|
824
|
+
kind: "category",
|
|
816
825
|
name: primaryCategory.name,
|
|
817
|
-
path: lastPlaceSlug ?
|
|
826
|
+
path: lastPlaceSlug ? jobsLocationCategoryPath(lastPlaceSlug, primaryCategory.slug) : jobsCategoryPath(primaryCategory.slug)
|
|
818
827
|
});
|
|
819
828
|
}
|
|
820
|
-
crumbs.push({ name: job.title });
|
|
829
|
+
crumbs.push({ kind: "job", name: job.title });
|
|
821
830
|
return crumbs;
|
|
822
831
|
}
|
|
823
832
|
|
|
824
833
|
export {
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
834
|
+
normalizeLocale,
|
|
835
|
+
formatSalaryStat,
|
|
836
|
+
formatSalaryStatRange,
|
|
828
837
|
SENIORITY_ORDER,
|
|
829
838
|
sortBySeniority,
|
|
830
839
|
buildSalaryFaq,
|
package/dist/doctor.js
CHANGED
|
@@ -57,7 +57,7 @@ function loadSkillCorpus(baseDir) {
|
|
|
57
57
|
).map((entry) => ({
|
|
58
58
|
path: entry.name,
|
|
59
59
|
content: (0, import_node_fs.readFileSync)((0, import_node_path.resolve)(skillDir, entry.name), "utf8")
|
|
60
|
-
})).sort((a, b) => a.path.
|
|
60
|
+
})).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
61
61
|
return {
|
|
62
62
|
...skill,
|
|
63
63
|
content: (0, import_node_fs.readFileSync)(skillPath, "utf8"),
|
package/dist/doctor.mjs
CHANGED
|
@@ -27,7 +27,7 @@ function loadSkillCorpus(baseDir) {
|
|
|
27
27
|
).map((entry) => ({
|
|
28
28
|
path: entry.name,
|
|
29
29
|
content: readFileSync(resolve(skillDir, entry.name), "utf8")
|
|
30
|
-
})).sort((a, b) => a.path.
|
|
30
|
+
})).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
31
31
|
return {
|
|
32
32
|
...skill,
|
|
33
33
|
content: readFileSync(skillPath, "utf8"),
|
package/dist/filters.d.mts
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
1
|
+
import { J as JobSort, E as EmploymentType, R as RemoteOption, S as Seniority } from './jobs-BuLpV8iy.mjs';
|
|
2
|
+
import './_spec-GVe6WAfT.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `@cavuno/board/filters` — the canonical listing-filter vocabulary and URL
|
|
6
|
+
* search-param parsing for jobs-listing routes.
|
|
7
|
+
*
|
|
8
|
+
* One greppable convention across every tenant frontend: the vocabulary
|
|
9
|
+
* arrays mirror the hosted board; seniority URL parsing follows the hosted
|
|
10
|
+
* semantics exactly (trim, lowercase, dedupe — hand-typed URLs are messy).
|
|
11
|
+
*
|
|
12
|
+
* Map parsed filters onto the wire like:
|
|
13
|
+
* ```
|
|
14
|
+
* companySlug: filters.company,
|
|
15
|
+
* seniority: filters.seniority,
|
|
16
|
+
* remoteOption: filters.remoteOption ? [filters.remoteOption] : undefined,
|
|
17
|
+
* ```
|
|
18
|
+
* Company slugs are the URL identity; the API accepts them directly via
|
|
19
|
+
* `companySlug` — never resolve slug→id client-side.
|
|
20
|
+
*
|
|
21
|
+
* Display labels for seniority / sort / remote options are application-owned
|
|
22
|
+
* chrome words — this entry only ships the wire vocabulary and
|
|
23
|
+
* parsers.
|
|
24
|
+
*/
|
|
4
25
|
|
|
5
26
|
declare const REMOTE_OPTIONS: readonly RemoteOption[];
|
|
6
27
|
/**
|
|
@@ -12,22 +33,6 @@ declare const EMPLOYMENT_TYPES: readonly EmploymentType[];
|
|
|
12
33
|
declare const SENIORITIES: readonly Seniority[];
|
|
13
34
|
declare const JOB_SORTS: readonly JobSort[];
|
|
14
35
|
declare const DEFAULT_SORT: JobSort;
|
|
15
|
-
/**
|
|
16
|
-
* Seniority display labels in the board language (lexicon-backed, en+de),
|
|
17
|
-
* ⊕ stored operator overrides (`jobCardLabels.seniority*`) when the
|
|
18
|
-
* `labels` bag is passed.
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* seniorityLabels('de').executive; // "Führungskraft"
|
|
22
|
-
*/
|
|
23
|
-
declare function seniorityLabels(locale: string, labels?: BoardLabelOverrides): Record<Seniority, string>;
|
|
24
|
-
/**
|
|
25
|
-
* Sort-dropdown labels in the board language, resolved from the copy
|
|
26
|
-
* catalog (`uiCopy(locale).jobCard`) ⊕ stored operator overrides
|
|
27
|
-
* (`jobCardLabels.aiRankedLabel` / `sortNewestLabel` / `sortSalaryHighLabel`)
|
|
28
|
-
* when the `labels` bag is passed.
|
|
29
|
-
*/
|
|
30
|
-
declare function sortLabels(locale: string, labels?: BoardLabelOverrides): Record<JobSort, string>;
|
|
31
36
|
interface ListingFilters {
|
|
32
37
|
q?: string;
|
|
33
38
|
remoteOption?: RemoteOption;
|
|
@@ -66,4 +71,4 @@ declare function parseCompany(raw: unknown): string[] | undefined;
|
|
|
66
71
|
*/
|
|
67
72
|
declare function parseListingFilters(search: Record<string, unknown>): ListingFilters;
|
|
68
73
|
|
|
69
|
-
export { DEFAULT_SORT, EMPLOYMENT_TYPES, JOB_SORTS, type ListingFilters, REMOTE_OPTIONS, SENIORITIES, parseCompany, parseListingFilters, parseSeniority
|
|
74
|
+
export { DEFAULT_SORT, EMPLOYMENT_TYPES, JOB_SORTS, type ListingFilters, REMOTE_OPTIONS, SENIORITIES, parseCompany, parseListingFilters, parseSeniority };
|
package/dist/filters.d.ts
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
1
|
+
import { J as JobSort, E as EmploymentType, R as RemoteOption, S as Seniority } from './jobs-QrbXOYB9.js';
|
|
2
|
+
import './_spec-GVe6WAfT.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `@cavuno/board/filters` — the canonical listing-filter vocabulary and URL
|
|
6
|
+
* search-param parsing for jobs-listing routes.
|
|
7
|
+
*
|
|
8
|
+
* One greppable convention across every tenant frontend: the vocabulary
|
|
9
|
+
* arrays mirror the hosted board; seniority URL parsing follows the hosted
|
|
10
|
+
* semantics exactly (trim, lowercase, dedupe — hand-typed URLs are messy).
|
|
11
|
+
*
|
|
12
|
+
* Map parsed filters onto the wire like:
|
|
13
|
+
* ```
|
|
14
|
+
* companySlug: filters.company,
|
|
15
|
+
* seniority: filters.seniority,
|
|
16
|
+
* remoteOption: filters.remoteOption ? [filters.remoteOption] : undefined,
|
|
17
|
+
* ```
|
|
18
|
+
* Company slugs are the URL identity; the API accepts them directly via
|
|
19
|
+
* `companySlug` — never resolve slug→id client-side.
|
|
20
|
+
*
|
|
21
|
+
* Display labels for seniority / sort / remote options are application-owned
|
|
22
|
+
* chrome words — this entry only ships the wire vocabulary and
|
|
23
|
+
* parsers.
|
|
24
|
+
*/
|
|
4
25
|
|
|
5
26
|
declare const REMOTE_OPTIONS: readonly RemoteOption[];
|
|
6
27
|
/**
|
|
@@ -12,22 +33,6 @@ declare const EMPLOYMENT_TYPES: readonly EmploymentType[];
|
|
|
12
33
|
declare const SENIORITIES: readonly Seniority[];
|
|
13
34
|
declare const JOB_SORTS: readonly JobSort[];
|
|
14
35
|
declare const DEFAULT_SORT: JobSort;
|
|
15
|
-
/**
|
|
16
|
-
* Seniority display labels in the board language (lexicon-backed, en+de),
|
|
17
|
-
* ⊕ stored operator overrides (`jobCardLabels.seniority*`) when the
|
|
18
|
-
* `labels` bag is passed.
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* seniorityLabels('de').executive; // "Führungskraft"
|
|
22
|
-
*/
|
|
23
|
-
declare function seniorityLabels(locale: string, labels?: BoardLabelOverrides): Record<Seniority, string>;
|
|
24
|
-
/**
|
|
25
|
-
* Sort-dropdown labels in the board language, resolved from the copy
|
|
26
|
-
* catalog (`uiCopy(locale).jobCard`) ⊕ stored operator overrides
|
|
27
|
-
* (`jobCardLabels.aiRankedLabel` / `sortNewestLabel` / `sortSalaryHighLabel`)
|
|
28
|
-
* when the `labels` bag is passed.
|
|
29
|
-
*/
|
|
30
|
-
declare function sortLabels(locale: string, labels?: BoardLabelOverrides): Record<JobSort, string>;
|
|
31
36
|
interface ListingFilters {
|
|
32
37
|
q?: string;
|
|
33
38
|
remoteOption?: RemoteOption;
|
|
@@ -66,4 +71,4 @@ declare function parseCompany(raw: unknown): string[] | undefined;
|
|
|
66
71
|
*/
|
|
67
72
|
declare function parseListingFilters(search: Record<string, unknown>): ListingFilters;
|
|
68
73
|
|
|
69
|
-
export { DEFAULT_SORT, EMPLOYMENT_TYPES, JOB_SORTS, type ListingFilters, REMOTE_OPTIONS, SENIORITIES, parseCompany, parseListingFilters, parseSeniority
|
|
74
|
+
export { DEFAULT_SORT, EMPLOYMENT_TYPES, JOB_SORTS, type ListingFilters, REMOTE_OPTIONS, SENIORITIES, parseCompany, parseListingFilters, parseSeniority };
|