@cavuno/board 3.0.0 → 3.2.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 +21 -0
- package/README.md +11 -0
- package/dist/blog-DGBHmExV.d.mts +29 -0
- package/dist/blog-iV9XEIGf.d.ts +29 -0
- package/dist/{salaries-ChSqDBAM.d.mts → board-BJbXd_9_.d.mts} +14 -27
- package/dist/{salaries-BahBpxWT.d.ts → board-JhdUWIoq.d.ts} +14 -27
- package/dist/breadcrumbs-1hMjcsqA.d.mts +171 -0
- package/dist/breadcrumbs-DexU07TT.d.ts +171 -0
- package/dist/chunk-2ETP5UH4.mjs +271 -0
- package/dist/chunk-DLSO6XXY.mjs +33 -0
- package/dist/chunk-IJCJ26SQ.mjs +596 -0
- package/dist/chunk-L7ZOYWHW.mjs +98 -0
- package/dist/chunk-LUGJWOT7.mjs +96 -0
- package/dist/chunk-NXY3OWGF.mjs +1060 -0
- package/dist/chunk-STE77MAT.mjs +844 -0
- package/dist/filters.mjs +7 -668
- package/dist/format.d.mts +2 -1
- package/dist/format.d.ts +2 -1
- package/dist/format.js +592 -523
- package/dist/format.mjs +19 -680
- package/dist/go.mjs +4 -29
- package/dist/index.d.mts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +1 -1
- package/dist/index.mjs +22 -278
- package/dist/paths.mjs +20 -77
- package/dist/route-contract.mjs +30 -1079
- package/dist/seo.d.mts +14 -171
- package/dist/seo.d.ts +14 -171
- package/dist/seo.js +1 -1
- package/dist/seo.mjs +24 -1399
- package/dist/server.d.mts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.mjs +5 -31
- package/dist/sitemap.d.mts +2 -2
- package/dist/sitemap.d.ts +2 -2
- package/dist/sitemap.mjs +20 -96
- package/dist/well-known.mjs +4 -421
- package/package.json +6 -3
- package/skills/cavuno-board-account/SKILL.md +4 -0
- package/skills/cavuno-board-api-client/SKILL.md +4 -0
- package/skills/cavuno-board-applications/SKILL.md +4 -0
- package/skills/cavuno-board-auth/SKILL.md +4 -0
- package/skills/cavuno-board-blog/SKILL.md +4 -0
- package/skills/cavuno-board-companies/SKILL.md +4 -0
- package/skills/cavuno-board-errors/SKILL.md +4 -0
- package/skills/cavuno-board-filters/SKILL.md +4 -0
- package/skills/cavuno-board-format/SKILL.md +4 -0
- package/skills/cavuno-board-i18n/SKILL.md +4 -0
- package/skills/cavuno-board-job-alerts/SKILL.md +4 -0
- package/skills/cavuno-board-jobs/SKILL.md +4 -0
- package/skills/cavuno-board-messaging/SKILL.md +4 -0
- package/skills/cavuno-board-paywall/SKILL.md +4 -0
- package/skills/cavuno-board-post-a-job/SKILL.md +4 -0
- package/skills/cavuno-board-salaries/SKILL.md +4 -0
- package/skills/cavuno-board-search-suggestions/SKILL.md +4 -0
- package/skills/cavuno-board-seo/SKILL.md +4 -0
- package/skills/cavuno-board-server-sessions/SKILL.md +4 -0
- package/skills/cavuno-board-setup/SKILL.md +4 -0
- package/skills/cavuno-board-sitemap/SKILL.md +4 -0
- package/skills/cavuno-board-smoke-test/SKILL.md +4 -0
- package/skills/manifest.json +1 -1
- package/dist/board-NE98PlwN.d.ts +0 -16
- package/dist/board-muu8BI8P.d.mts +0 -16
package/dist/seo.d.mts
CHANGED
|
@@ -1,59 +1,10 @@
|
|
|
1
|
-
import { P as PublicBlogPostSummary, B as BlogAuthorEmbed
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import { B as BoardLabelOverrides } from './ui-copy-CCkz6CVF.mjs';
|
|
1
|
+
import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-DGBHmExV.mjs';
|
|
2
|
+
import { J as JsonLdObject } from './breadcrumbs-1hMjcsqA.mjs';
|
|
3
|
+
export { A as ALL_COUNTRY_CODES, B as BreadcrumbItemInput, F as FaqItem, c as JsonLdBoard, S as SENIORITY_ORDER, b as buildJobBreadcrumbs, d as buildSalaryFaq, e as companyCategorySalaryJsonLd, g as companySalaryJsonLd, h as createBreadcrumbJsonLd, i as createJobPostingJsonLd, j as crossAxisSalaryJsonLd, k as faqJsonLd, f as formatRange, l as formatSeniority, a as formatUsd, m as itemListJsonLd, o as locationSalaryJsonLd, n as normalizeWebsiteUrl, s as skillSalaryJsonLd, p as sortBySeniority, t as titleSalaryJsonLd } from './breadcrumbs-1hMjcsqA.mjs';
|
|
5
4
|
import './_spec-nkWAraS0.mjs';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* types, transcribed field-by-field from the hosted board's generator
|
|
10
|
-
* (the hosted board implementation + `job-posting-location-json-ld.ts`) and
|
|
11
|
-
* tested against the hosted behavior.
|
|
12
|
-
*
|
|
13
|
-
* JSON-LD structure is locale-neutral per schema.org — no board-language
|
|
14
|
-
* parameter here; the only display strings are wire values passed through.
|
|
15
|
-
*
|
|
16
|
-
* Named exclusions (hosted behaviours with no wire twin, recorded in the
|
|
17
|
-
* public API contract):
|
|
18
|
-
* - `board.companyLegalName` — hosted falls back to it for the
|
|
19
|
-
* organization name between `company.name` and `board.name`; the wire
|
|
20
|
-
* board context does not expose it.
|
|
21
|
-
* - `board.companyWebsiteUrl` — hosted falls back to it for `sameAs` when
|
|
22
|
-
* the company has no website; not on the wire.
|
|
23
|
-
* - the hosted `job.place`/`locationLabel` jobLocation fallback (used when
|
|
24
|
-
* a job has no office locations) — the wire `PublicJob` carries no
|
|
25
|
-
* resolved place geo, only `officeLocations`.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
type JsonLdObject = Record<string, unknown>;
|
|
29
|
-
/** The only board fields JSON-LD needs — keeps callers' shapes flexible. */
|
|
30
|
-
type JsonLdBoard = Pick<PublicBoard, 'name' | 'logoUrl'>;
|
|
31
|
-
/**
|
|
32
|
-
* Worldwide-remote jobs must still emit `applicantLocationRequirements`
|
|
33
|
-
* next to TELECOMMUTE (Google requires a location signal), so the hosted
|
|
34
|
-
* board — and this transcription — lists every country it recognises.
|
|
35
|
-
*
|
|
36
|
-
* This is the hosted board's exact country catalog: sorted by English common
|
|
37
|
-
* name, includes `XK` (Kosovo), and excludes `KP` (North Korea). tested
|
|
38
|
-
* against the hosted list so the two cannot drift.
|
|
39
|
-
*/
|
|
40
|
-
declare const ALL_COUNTRY_CODES: readonly ["AF", "AX", "AL", "DZ", "AS", "AD", "AO", "AI", "AQ", "AG", "AR", "AM", "AW", "AU", "AT", "AZ", "BS", "BH", "BD", "BB", "BY", "BE", "BZ", "BJ", "BM", "BT", "BO", "BA", "BW", "BV", "BR", "IO", "VG", "BN", "BG", "BF", "BI", "KH", "CM", "CA", "CV", "BQ", "KY", "CF", "TD", "CL", "CN", "CX", "CC", "CO", "KM", "CK", "CR", "HR", "CU", "CW", "CY", "CZ", "DK", "DJ", "DM", "DO", "CD", "EC", "EG", "SV", "GQ", "ER", "EE", "SZ", "ET", "FK", "FO", "FJ", "FI", "FR", "GF", "PF", "TF", "GA", "GM", "GE", "DE", "GH", "GI", "GR", "GL", "GD", "GP", "GU", "GT", "GG", "GN", "GW", "GY", "HT", "HM", "HN", "HK", "HU", "IS", "IN", "ID", "IR", "IQ", "IE", "IM", "IL", "IT", "CI", "JM", "JP", "JE", "JO", "KZ", "KE", "KI", "XK", "KW", "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LI", "LT", "LU", "MO", "MG", "MW", "MY", "MV", "ML", "MT", "MH", "MQ", "MR", "MU", "YT", "MX", "FM", "MD", "MC", "MN", "ME", "MS", "MA", "MZ", "MM", "NA", "NR", "NP", "NL", "NC", "NZ", "NI", "NE", "NG", "NU", "NF", "MK", "MP", "NO", "OM", "PK", "PW", "PS", "PA", "PG", "PY", "PE", "PH", "PN", "PL", "PT", "PR", "QA", "CG", "RE", "RO", "RU", "RW", "BL", "SH", "KN", "LC", "MF", "PM", "VC", "WS", "SM", "ST", "SA", "SN", "RS", "SC", "SL", "SG", "SX", "SK", "SI", "SB", "SO", "ZA", "GS", "KR", "SS", "ES", "LK", "SD", "SR", "SJ", "SE", "CH", "SY", "TW", "TJ", "TZ", "TH", "TL", "TG", "TK", "TO", "TT", "TN", "TR", "TM", "TC", "TV", "UG", "UA", "AE", "GB", "US", "UM", "VI", "UY", "UZ", "VU", "VA", "VE", "VN", "WF", "EH", "YE", "ZM", "ZW"];
|
|
41
|
-
/**
|
|
42
|
-
* Build the Google for Jobs `JobPosting` JSON-LD object for a job detail
|
|
43
|
-
* page, or `null` when nothing renderable remains after pruning. Embed the
|
|
44
|
-
* result in a `<script type="application/ld+json">` tag.
|
|
45
|
-
*/
|
|
46
|
-
declare function createJobPostingJsonLd({ job, board, shareUrl, }: {
|
|
47
|
-
job: PublicJob;
|
|
48
|
-
board: JsonLdBoard;
|
|
49
|
-
shareUrl: string;
|
|
50
|
-
}): JsonLdObject | null;
|
|
51
|
-
/**
|
|
52
|
-
* Prefix `https://` onto scheme-less company websites; `null` for
|
|
53
|
-
* blank input (hosted shape — a whitespace-only website never becomes
|
|
54
|
-
* a bare `https://` `sameAs`).
|
|
55
|
-
*/
|
|
56
|
-
declare function normalizeWebsiteUrl(website: string): string | null;
|
|
5
|
+
import './board-BJbXd_9_.mjs';
|
|
6
|
+
import './jobs-lVvKCBCU.mjs';
|
|
7
|
+
import './ui-copy-CCkz6CVF.mjs';
|
|
57
8
|
|
|
58
9
|
/**
|
|
59
10
|
* Blog structured data on the `@cavuno/board` wire types, transcribed from
|
|
@@ -108,37 +59,6 @@ declare function createAuthorProfileJsonLd({ author, canonical, description, ori
|
|
|
108
59
|
totalPosts: number;
|
|
109
60
|
}): JsonLdObject | null;
|
|
110
61
|
|
|
111
|
-
interface BreadcrumbItemInput {
|
|
112
|
-
label: string | null | undefined;
|
|
113
|
-
href?: string | null;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Build a `BreadcrumbList`, hosted semantics: labels are trimmed and empty
|
|
117
|
-
* items dropped; fewer than 2 surviving items → `null` (a single crumb is
|
|
118
|
-
* not a trail); the current page (no `href`) omits `item` per schema.org.
|
|
119
|
-
* Relative hrefs resolve against `options.origin`; without an origin a
|
|
120
|
-
* relative item is omitted (never emit a relative `item` URL).
|
|
121
|
-
*/
|
|
122
|
-
declare function createBreadcrumbJsonLd(items: BreadcrumbItemInput[], options?: {
|
|
123
|
-
origin?: string | null;
|
|
124
|
-
}): JsonLdObject | null;
|
|
125
|
-
/**
|
|
126
|
-
* Home › Jobs › [country › region › city] › primaryCategory › Title.
|
|
127
|
-
* The place crumbs link into the listing routes (`/jobs/locations/:slug`);
|
|
128
|
-
* the category crumb nests under the most-specific place when present
|
|
129
|
-
* (`/jobs/locations/:place/:category`), else `/jobs/:category`. The last
|
|
130
|
-
* crumb (the job title) carries no `path` — the current page. Mirrors
|
|
131
|
-
* page.tsx:336-367.
|
|
132
|
-
*
|
|
133
|
-
* The Home/Jobs crumb names resolve from the copy catalog per board
|
|
134
|
-
* language ⊕ operator overrides; omitting `language` keeps the
|
|
135
|
-
* English source, so existing call sites render unchanged.
|
|
136
|
-
*/
|
|
137
|
-
declare function buildJobBreadcrumbs(job: PublicJob, language?: string, labels?: BoardLabelOverrides): Array<{
|
|
138
|
-
name: string;
|
|
139
|
-
path?: string;
|
|
140
|
-
}>;
|
|
141
|
-
|
|
142
62
|
/**
|
|
143
63
|
* Framework-neutral `<head>` + structural JSON-LD builders for jobs-listing
|
|
144
64
|
* pages. Locale-neutral pass-through: the caller supplies the
|
|
@@ -157,6 +77,13 @@ interface ListingHeadOptions {
|
|
|
157
77
|
heading: string;
|
|
158
78
|
/** Result count — prefixed into the title (`N heading`). */
|
|
159
79
|
count?: number;
|
|
80
|
+
/**
|
|
81
|
+
* Board language (BCP-47). When supplied, `count` is grouped for that
|
|
82
|
+
* locale in the title and description — `1,225 Jobs` / `1.225 Jobs` —
|
|
83
|
+
* matching how listing bodies render the same number. Omit to keep the
|
|
84
|
+
* ungrouped digits the hosted structure has always emitted.
|
|
85
|
+
*/
|
|
86
|
+
language?: string;
|
|
160
87
|
}
|
|
161
88
|
/**
|
|
162
89
|
* Meta/link descriptors for a jobs-listing page — title (with result
|
|
@@ -207,88 +134,4 @@ declare function listingJsonLd(options: {
|
|
|
207
134
|
jobs?: JobLink[];
|
|
208
135
|
}): JsonLdObject[];
|
|
209
136
|
|
|
210
|
-
|
|
211
|
-
* Compact USD amount in the board language (`$90K`, de: `90.000 $`) — the
|
|
212
|
-
* hosted salary-page money formatter. USD-hardcoded (hosted quirk); the
|
|
213
|
-
* locale drives digits, grouping, and symbol placement only.
|
|
214
|
-
*/
|
|
215
|
-
declare function formatUsd(locale: string, value: number): string;
|
|
216
|
-
/** `formatUsd(min) – formatUsd(max)` with the hosted spaced en dash. */
|
|
217
|
-
declare function formatRange(locale: string, min: number, max: number): string;
|
|
218
|
-
/**
|
|
219
|
-
* Seniority display label. Precedence (hosted shape): owner override >
|
|
220
|
-
* board-language lexicon (en = the English source labels) > title-case
|
|
221
|
-
* fallback for an unknown key.
|
|
222
|
-
*/
|
|
223
|
-
declare function formatSeniority(locale: string, value: string, overrides?: Record<string, string>): string;
|
|
224
|
-
/** The canonical seniority ladder order the hosted salary pages sort by. */
|
|
225
|
-
declare const SENIORITY_ORDER: readonly ["entry_level", "associate", "mid_level", "senior", "lead", "principal", "director", "executive"];
|
|
226
|
-
/** Sort rows by `SENIORITY_ORDER` (unknown keys sink to the end). Non-mutating. */
|
|
227
|
-
declare function sortBySeniority<T extends {
|
|
228
|
-
seniority: string;
|
|
229
|
-
}>(items: T[]): T[];
|
|
230
|
-
interface FaqItem {
|
|
231
|
-
q: string;
|
|
232
|
-
a: string;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* A templated salary FAQ (interim — see the module doc). The sentences are
|
|
236
|
-
* English; the embedded range is board-language-formatted via `formatRange`
|
|
237
|
-
* (the only part hosted localizes). Empty when there is no overall figure.
|
|
238
|
-
*/
|
|
239
|
-
declare function buildSalaryFaq(locale: string, label: string, overall: {
|
|
240
|
-
avgMin: number;
|
|
241
|
-
avgMax: number;
|
|
242
|
-
jobCount: number;
|
|
243
|
-
} | null): FaqItem[];
|
|
244
|
-
/** An `ItemList` for a salary index page (the listing's items + their URLs). */
|
|
245
|
-
declare function itemListJsonLd(items: {
|
|
246
|
-
name: string;
|
|
247
|
-
url: string;
|
|
248
|
-
}[]): JsonLdObject | null;
|
|
249
|
-
/** A `FAQPage` from `buildSalaryFaq` items (or any `{q,a}` list). */
|
|
250
|
-
declare function faqJsonLd(faqs: FaqItem[]): JsonLdObject | null;
|
|
251
|
-
/**
|
|
252
|
-
* `Occupation` for a job-title salary page. Per-seniority distribution
|
|
253
|
-
* names embed the board-language seniority label (`formatSeniority`).
|
|
254
|
-
*/
|
|
255
|
-
declare function titleSalaryJsonLd(locale: string, d: TitleSalaryDetail): JsonLdObject | null;
|
|
256
|
-
/** `Occupation` for a skill salary page (overall distribution + median). */
|
|
257
|
-
declare function skillSalaryJsonLd(d: SkillSalaryDetail): JsonLdObject | null;
|
|
258
|
-
/**
|
|
259
|
-
* `Occupation` for a location salary page. City-level pages only (the
|
|
260
|
-
* hosted page gates on city/locality); `null` otherwise.
|
|
261
|
-
*/
|
|
262
|
-
declare function locationSalaryJsonLd(d: LocationSalaryDetail): JsonLdObject | null;
|
|
263
|
-
/**
|
|
264
|
-
* Cross-axis (title×location / skill×location) `Occupation` JSON-LD. Takes
|
|
265
|
-
* primitives to stay decoupled from the two cross-axis detail wire types.
|
|
266
|
-
*/
|
|
267
|
-
declare function crossAxisSalaryJsonLd(locale: string, args: {
|
|
268
|
-
name: string;
|
|
269
|
-
placeName: string;
|
|
270
|
-
countryCode: string;
|
|
271
|
-
overall: {
|
|
272
|
-
avgMin: number;
|
|
273
|
-
avgMax: number;
|
|
274
|
-
p25Min: number | null;
|
|
275
|
-
p75Max: number | null;
|
|
276
|
-
} | null;
|
|
277
|
-
bySeniority: {
|
|
278
|
-
seniority: string;
|
|
279
|
-
avgSalaryMin: number;
|
|
280
|
-
avgSalaryMax: number;
|
|
281
|
-
}[];
|
|
282
|
-
currency: string;
|
|
283
|
-
}): JsonLdObject | null;
|
|
284
|
-
/**
|
|
285
|
-
* `OccupationAggregationByEmployer` for a company's salary overview —
|
|
286
|
-
* mirrors the hosted company-salary page's Google-salary structured data
|
|
287
|
-
* (base + per-seniority distributions, the board median/IQR baseline as
|
|
288
|
-
* the aggregate stats).
|
|
289
|
-
*/
|
|
290
|
-
declare function companySalaryJsonLd(locale: string, d: CompanySalary): JsonLdObject | null;
|
|
291
|
-
/** `Occupation` for one job category at a company (the hosted category page). */
|
|
292
|
-
declare function companyCategorySalaryJsonLd(locale: string, d: CompanyCategorySalary): JsonLdObject | null;
|
|
293
|
-
|
|
294
|
-
export { ALL_COUNTRY_CODES, type ArticleJsonLdPost, type BreadcrumbItemInput, type FaqItem, type JsonLdBoard, type JsonLdObject, type ListingHeadOptions, SENIORITY_ORDER, buildJobBreadcrumbs, buildSalaryFaq, companyCategorySalaryJsonLd, companySalaryJsonLd, createAuthorProfileJsonLd, createBlogArticleJsonLd, createBreadcrumbJsonLd, createJobPostingJsonLd, crossAxisSalaryJsonLd, faqJsonLd, formatRange, formatSeniority, formatUsd, itemListJsonLd, listingHead, listingJsonLd, locationSalaryJsonLd, normalizeWebsiteUrl, skillSalaryJsonLd, sortBySeniority, titleSalaryJsonLd };
|
|
137
|
+
export { type ArticleJsonLdPost, JsonLdObject, type ListingHeadOptions, createAuthorProfileJsonLd, createBlogArticleJsonLd, listingHead, listingJsonLd };
|
package/dist/seo.d.ts
CHANGED
|
@@ -1,59 +1,10 @@
|
|
|
1
|
-
import { P as PublicBlogPostSummary, B as BlogAuthorEmbed
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import { B as BoardLabelOverrides } from './ui-copy-CCkz6CVF.js';
|
|
1
|
+
import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-iV9XEIGf.js';
|
|
2
|
+
import { J as JsonLdObject } from './breadcrumbs-DexU07TT.js';
|
|
3
|
+
export { A as ALL_COUNTRY_CODES, B as BreadcrumbItemInput, F as FaqItem, c as JsonLdBoard, S as SENIORITY_ORDER, b as buildJobBreadcrumbs, d as buildSalaryFaq, e as companyCategorySalaryJsonLd, g as companySalaryJsonLd, h as createBreadcrumbJsonLd, i as createJobPostingJsonLd, j as crossAxisSalaryJsonLd, k as faqJsonLd, f as formatRange, l as formatSeniority, a as formatUsd, m as itemListJsonLd, o as locationSalaryJsonLd, n as normalizeWebsiteUrl, s as skillSalaryJsonLd, p as sortBySeniority, t as titleSalaryJsonLd } from './breadcrumbs-DexU07TT.js';
|
|
5
4
|
import './_spec-nkWAraS0.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* types, transcribed field-by-field from the hosted board's generator
|
|
10
|
-
* (the hosted board implementation + `job-posting-location-json-ld.ts`) and
|
|
11
|
-
* tested against the hosted behavior.
|
|
12
|
-
*
|
|
13
|
-
* JSON-LD structure is locale-neutral per schema.org — no board-language
|
|
14
|
-
* parameter here; the only display strings are wire values passed through.
|
|
15
|
-
*
|
|
16
|
-
* Named exclusions (hosted behaviours with no wire twin, recorded in the
|
|
17
|
-
* public API contract):
|
|
18
|
-
* - `board.companyLegalName` — hosted falls back to it for the
|
|
19
|
-
* organization name between `company.name` and `board.name`; the wire
|
|
20
|
-
* board context does not expose it.
|
|
21
|
-
* - `board.companyWebsiteUrl` — hosted falls back to it for `sameAs` when
|
|
22
|
-
* the company has no website; not on the wire.
|
|
23
|
-
* - the hosted `job.place`/`locationLabel` jobLocation fallback (used when
|
|
24
|
-
* a job has no office locations) — the wire `PublicJob` carries no
|
|
25
|
-
* resolved place geo, only `officeLocations`.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
type JsonLdObject = Record<string, unknown>;
|
|
29
|
-
/** The only board fields JSON-LD needs — keeps callers' shapes flexible. */
|
|
30
|
-
type JsonLdBoard = Pick<PublicBoard, 'name' | 'logoUrl'>;
|
|
31
|
-
/**
|
|
32
|
-
* Worldwide-remote jobs must still emit `applicantLocationRequirements`
|
|
33
|
-
* next to TELECOMMUTE (Google requires a location signal), so the hosted
|
|
34
|
-
* board — and this transcription — lists every country it recognises.
|
|
35
|
-
*
|
|
36
|
-
* This is the hosted board's exact country catalog: sorted by English common
|
|
37
|
-
* name, includes `XK` (Kosovo), and excludes `KP` (North Korea). tested
|
|
38
|
-
* against the hosted list so the two cannot drift.
|
|
39
|
-
*/
|
|
40
|
-
declare const ALL_COUNTRY_CODES: readonly ["AF", "AX", "AL", "DZ", "AS", "AD", "AO", "AI", "AQ", "AG", "AR", "AM", "AW", "AU", "AT", "AZ", "BS", "BH", "BD", "BB", "BY", "BE", "BZ", "BJ", "BM", "BT", "BO", "BA", "BW", "BV", "BR", "IO", "VG", "BN", "BG", "BF", "BI", "KH", "CM", "CA", "CV", "BQ", "KY", "CF", "TD", "CL", "CN", "CX", "CC", "CO", "KM", "CK", "CR", "HR", "CU", "CW", "CY", "CZ", "DK", "DJ", "DM", "DO", "CD", "EC", "EG", "SV", "GQ", "ER", "EE", "SZ", "ET", "FK", "FO", "FJ", "FI", "FR", "GF", "PF", "TF", "GA", "GM", "GE", "DE", "GH", "GI", "GR", "GL", "GD", "GP", "GU", "GT", "GG", "GN", "GW", "GY", "HT", "HM", "HN", "HK", "HU", "IS", "IN", "ID", "IR", "IQ", "IE", "IM", "IL", "IT", "CI", "JM", "JP", "JE", "JO", "KZ", "KE", "KI", "XK", "KW", "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LI", "LT", "LU", "MO", "MG", "MW", "MY", "MV", "ML", "MT", "MH", "MQ", "MR", "MU", "YT", "MX", "FM", "MD", "MC", "MN", "ME", "MS", "MA", "MZ", "MM", "NA", "NR", "NP", "NL", "NC", "NZ", "NI", "NE", "NG", "NU", "NF", "MK", "MP", "NO", "OM", "PK", "PW", "PS", "PA", "PG", "PY", "PE", "PH", "PN", "PL", "PT", "PR", "QA", "CG", "RE", "RO", "RU", "RW", "BL", "SH", "KN", "LC", "MF", "PM", "VC", "WS", "SM", "ST", "SA", "SN", "RS", "SC", "SL", "SG", "SX", "SK", "SI", "SB", "SO", "ZA", "GS", "KR", "SS", "ES", "LK", "SD", "SR", "SJ", "SE", "CH", "SY", "TW", "TJ", "TZ", "TH", "TL", "TG", "TK", "TO", "TT", "TN", "TR", "TM", "TC", "TV", "UG", "UA", "AE", "GB", "US", "UM", "VI", "UY", "UZ", "VU", "VA", "VE", "VN", "WF", "EH", "YE", "ZM", "ZW"];
|
|
41
|
-
/**
|
|
42
|
-
* Build the Google for Jobs `JobPosting` JSON-LD object for a job detail
|
|
43
|
-
* page, or `null` when nothing renderable remains after pruning. Embed the
|
|
44
|
-
* result in a `<script type="application/ld+json">` tag.
|
|
45
|
-
*/
|
|
46
|
-
declare function createJobPostingJsonLd({ job, board, shareUrl, }: {
|
|
47
|
-
job: PublicJob;
|
|
48
|
-
board: JsonLdBoard;
|
|
49
|
-
shareUrl: string;
|
|
50
|
-
}): JsonLdObject | null;
|
|
51
|
-
/**
|
|
52
|
-
* Prefix `https://` onto scheme-less company websites; `null` for
|
|
53
|
-
* blank input (hosted shape — a whitespace-only website never becomes
|
|
54
|
-
* a bare `https://` `sameAs`).
|
|
55
|
-
*/
|
|
56
|
-
declare function normalizeWebsiteUrl(website: string): string | null;
|
|
5
|
+
import './board-JhdUWIoq.js';
|
|
6
|
+
import './jobs-BiEvL9d7.js';
|
|
7
|
+
import './ui-copy-CCkz6CVF.js';
|
|
57
8
|
|
|
58
9
|
/**
|
|
59
10
|
* Blog structured data on the `@cavuno/board` wire types, transcribed from
|
|
@@ -108,37 +59,6 @@ declare function createAuthorProfileJsonLd({ author, canonical, description, ori
|
|
|
108
59
|
totalPosts: number;
|
|
109
60
|
}): JsonLdObject | null;
|
|
110
61
|
|
|
111
|
-
interface BreadcrumbItemInput {
|
|
112
|
-
label: string | null | undefined;
|
|
113
|
-
href?: string | null;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Build a `BreadcrumbList`, hosted semantics: labels are trimmed and empty
|
|
117
|
-
* items dropped; fewer than 2 surviving items → `null` (a single crumb is
|
|
118
|
-
* not a trail); the current page (no `href`) omits `item` per schema.org.
|
|
119
|
-
* Relative hrefs resolve against `options.origin`; without an origin a
|
|
120
|
-
* relative item is omitted (never emit a relative `item` URL).
|
|
121
|
-
*/
|
|
122
|
-
declare function createBreadcrumbJsonLd(items: BreadcrumbItemInput[], options?: {
|
|
123
|
-
origin?: string | null;
|
|
124
|
-
}): JsonLdObject | null;
|
|
125
|
-
/**
|
|
126
|
-
* Home › Jobs › [country › region › city] › primaryCategory › Title.
|
|
127
|
-
* The place crumbs link into the listing routes (`/jobs/locations/:slug`);
|
|
128
|
-
* the category crumb nests under the most-specific place when present
|
|
129
|
-
* (`/jobs/locations/:place/:category`), else `/jobs/:category`. The last
|
|
130
|
-
* crumb (the job title) carries no `path` — the current page. Mirrors
|
|
131
|
-
* page.tsx:336-367.
|
|
132
|
-
*
|
|
133
|
-
* The Home/Jobs crumb names resolve from the copy catalog per board
|
|
134
|
-
* language ⊕ operator overrides; omitting `language` keeps the
|
|
135
|
-
* English source, so existing call sites render unchanged.
|
|
136
|
-
*/
|
|
137
|
-
declare function buildJobBreadcrumbs(job: PublicJob, language?: string, labels?: BoardLabelOverrides): Array<{
|
|
138
|
-
name: string;
|
|
139
|
-
path?: string;
|
|
140
|
-
}>;
|
|
141
|
-
|
|
142
62
|
/**
|
|
143
63
|
* Framework-neutral `<head>` + structural JSON-LD builders for jobs-listing
|
|
144
64
|
* pages. Locale-neutral pass-through: the caller supplies the
|
|
@@ -157,6 +77,13 @@ interface ListingHeadOptions {
|
|
|
157
77
|
heading: string;
|
|
158
78
|
/** Result count — prefixed into the title (`N heading`). */
|
|
159
79
|
count?: number;
|
|
80
|
+
/**
|
|
81
|
+
* Board language (BCP-47). When supplied, `count` is grouped for that
|
|
82
|
+
* locale in the title and description — `1,225 Jobs` / `1.225 Jobs` —
|
|
83
|
+
* matching how listing bodies render the same number. Omit to keep the
|
|
84
|
+
* ungrouped digits the hosted structure has always emitted.
|
|
85
|
+
*/
|
|
86
|
+
language?: string;
|
|
160
87
|
}
|
|
161
88
|
/**
|
|
162
89
|
* Meta/link descriptors for a jobs-listing page — title (with result
|
|
@@ -207,88 +134,4 @@ declare function listingJsonLd(options: {
|
|
|
207
134
|
jobs?: JobLink[];
|
|
208
135
|
}): JsonLdObject[];
|
|
209
136
|
|
|
210
|
-
|
|
211
|
-
* Compact USD amount in the board language (`$90K`, de: `90.000 $`) — the
|
|
212
|
-
* hosted salary-page money formatter. USD-hardcoded (hosted quirk); the
|
|
213
|
-
* locale drives digits, grouping, and symbol placement only.
|
|
214
|
-
*/
|
|
215
|
-
declare function formatUsd(locale: string, value: number): string;
|
|
216
|
-
/** `formatUsd(min) – formatUsd(max)` with the hosted spaced en dash. */
|
|
217
|
-
declare function formatRange(locale: string, min: number, max: number): string;
|
|
218
|
-
/**
|
|
219
|
-
* Seniority display label. Precedence (hosted shape): owner override >
|
|
220
|
-
* board-language lexicon (en = the English source labels) > title-case
|
|
221
|
-
* fallback for an unknown key.
|
|
222
|
-
*/
|
|
223
|
-
declare function formatSeniority(locale: string, value: string, overrides?: Record<string, string>): string;
|
|
224
|
-
/** The canonical seniority ladder order the hosted salary pages sort by. */
|
|
225
|
-
declare const SENIORITY_ORDER: readonly ["entry_level", "associate", "mid_level", "senior", "lead", "principal", "director", "executive"];
|
|
226
|
-
/** Sort rows by `SENIORITY_ORDER` (unknown keys sink to the end). Non-mutating. */
|
|
227
|
-
declare function sortBySeniority<T extends {
|
|
228
|
-
seniority: string;
|
|
229
|
-
}>(items: T[]): T[];
|
|
230
|
-
interface FaqItem {
|
|
231
|
-
q: string;
|
|
232
|
-
a: string;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* A templated salary FAQ (interim — see the module doc). The sentences are
|
|
236
|
-
* English; the embedded range is board-language-formatted via `formatRange`
|
|
237
|
-
* (the only part hosted localizes). Empty when there is no overall figure.
|
|
238
|
-
*/
|
|
239
|
-
declare function buildSalaryFaq(locale: string, label: string, overall: {
|
|
240
|
-
avgMin: number;
|
|
241
|
-
avgMax: number;
|
|
242
|
-
jobCount: number;
|
|
243
|
-
} | null): FaqItem[];
|
|
244
|
-
/** An `ItemList` for a salary index page (the listing's items + their URLs). */
|
|
245
|
-
declare function itemListJsonLd(items: {
|
|
246
|
-
name: string;
|
|
247
|
-
url: string;
|
|
248
|
-
}[]): JsonLdObject | null;
|
|
249
|
-
/** A `FAQPage` from `buildSalaryFaq` items (or any `{q,a}` list). */
|
|
250
|
-
declare function faqJsonLd(faqs: FaqItem[]): JsonLdObject | null;
|
|
251
|
-
/**
|
|
252
|
-
* `Occupation` for a job-title salary page. Per-seniority distribution
|
|
253
|
-
* names embed the board-language seniority label (`formatSeniority`).
|
|
254
|
-
*/
|
|
255
|
-
declare function titleSalaryJsonLd(locale: string, d: TitleSalaryDetail): JsonLdObject | null;
|
|
256
|
-
/** `Occupation` for a skill salary page (overall distribution + median). */
|
|
257
|
-
declare function skillSalaryJsonLd(d: SkillSalaryDetail): JsonLdObject | null;
|
|
258
|
-
/**
|
|
259
|
-
* `Occupation` for a location salary page. City-level pages only (the
|
|
260
|
-
* hosted page gates on city/locality); `null` otherwise.
|
|
261
|
-
*/
|
|
262
|
-
declare function locationSalaryJsonLd(d: LocationSalaryDetail): JsonLdObject | null;
|
|
263
|
-
/**
|
|
264
|
-
* Cross-axis (title×location / skill×location) `Occupation` JSON-LD. Takes
|
|
265
|
-
* primitives to stay decoupled from the two cross-axis detail wire types.
|
|
266
|
-
*/
|
|
267
|
-
declare function crossAxisSalaryJsonLd(locale: string, args: {
|
|
268
|
-
name: string;
|
|
269
|
-
placeName: string;
|
|
270
|
-
countryCode: string;
|
|
271
|
-
overall: {
|
|
272
|
-
avgMin: number;
|
|
273
|
-
avgMax: number;
|
|
274
|
-
p25Min: number | null;
|
|
275
|
-
p75Max: number | null;
|
|
276
|
-
} | null;
|
|
277
|
-
bySeniority: {
|
|
278
|
-
seniority: string;
|
|
279
|
-
avgSalaryMin: number;
|
|
280
|
-
avgSalaryMax: number;
|
|
281
|
-
}[];
|
|
282
|
-
currency: string;
|
|
283
|
-
}): JsonLdObject | null;
|
|
284
|
-
/**
|
|
285
|
-
* `OccupationAggregationByEmployer` for a company's salary overview —
|
|
286
|
-
* mirrors the hosted company-salary page's Google-salary structured data
|
|
287
|
-
* (base + per-seniority distributions, the board median/IQR baseline as
|
|
288
|
-
* the aggregate stats).
|
|
289
|
-
*/
|
|
290
|
-
declare function companySalaryJsonLd(locale: string, d: CompanySalary): JsonLdObject | null;
|
|
291
|
-
/** `Occupation` for one job category at a company (the hosted category page). */
|
|
292
|
-
declare function companyCategorySalaryJsonLd(locale: string, d: CompanyCategorySalary): JsonLdObject | null;
|
|
293
|
-
|
|
294
|
-
export { ALL_COUNTRY_CODES, type ArticleJsonLdPost, type BreadcrumbItemInput, type FaqItem, type JsonLdBoard, type JsonLdObject, type ListingHeadOptions, SENIORITY_ORDER, buildJobBreadcrumbs, buildSalaryFaq, companyCategorySalaryJsonLd, companySalaryJsonLd, createAuthorProfileJsonLd, createBlogArticleJsonLd, createBreadcrumbJsonLd, createJobPostingJsonLd, crossAxisSalaryJsonLd, faqJsonLd, formatRange, formatSeniority, formatUsd, itemListJsonLd, listingHead, listingJsonLd, locationSalaryJsonLd, normalizeWebsiteUrl, skillSalaryJsonLd, sortBySeniority, titleSalaryJsonLd };
|
|
137
|
+
export { type ArticleJsonLdPost, JsonLdObject, type ListingHeadOptions, createAuthorProfileJsonLd, createBlogArticleJsonLd, listingHead, listingJsonLd };
|
package/dist/seo.js
CHANGED
|
@@ -1165,7 +1165,7 @@ function pruneJsonLd(value) {
|
|
|
1165
1165
|
|
|
1166
1166
|
// src/seo/listing.ts
|
|
1167
1167
|
function listingHead(options) {
|
|
1168
|
-
const countPrefix = typeof options.count === "number" ? `${options.count} ` : "";
|
|
1168
|
+
const countPrefix = typeof options.count === "number" ? `${options.language ? new Intl.NumberFormat(options.language).format(options.count) : options.count} ` : "";
|
|
1169
1169
|
const title = `${countPrefix}${options.heading} | ${options.boardName}`;
|
|
1170
1170
|
const description = `Browse ${countPrefix}${options.heading.toLowerCase()} on ${options.boardName}.`;
|
|
1171
1171
|
const url = `${options.origin}${options.path}`;
|