import { L as LocationValue } from '../index-CTzpbW81.js'; var vocabularies = { schema: "https://schema.org/", bibo: "http://purl.org/ontology/bibo/", dcterms: "http://purl.org/dc/terms/", foaf: "http://xmlns.com/foaf/0.1/", org: "http://www.w3.org/ns/org#", prism: "http://prismstandard.org/namespaces/basic/2.1/", event: "http://purl.org/NET/c4dm/event.owl#", skos: "http://www.w3.org/2004/02/skos/core#" }; var document = { vocabularies: vocabularies}; /** * Reconciliation between `id.sifa.*` lexicon terms and existing RDF * vocabularies. * * The facts live in sifa-lexicons, as `x-skos:*` annotations on the lexicon * defs and properties. Those annotations are published to the authority PDS, * so a third party resolving `id.sifa.*` already reads them; that makes the * lexicons the source of truth and `./term-mappings.json` a derived copy, * refreshed by `scripts/sync-term-mappings.mjs` and drift-checked in CI. * * To change a mapping, change the lexicon, not this file. * * Scope note: RDF is adopted here as *vocabulary only*. Sifa records are * Lexicon JSON on the AT Protocol; nothing in this module changes how records * are stored or transmitted. A mapping is a one-directional annotation over a * lexicon designed on its own merits, never a constraint on lexicon design. * When a term does not fit, the correct answer is `noMatch`, not a different * lexicon. */ /** Vocabulary prefix -> namespace IRI. */ declare const VOCABULARIES: Readonly>; type VocabularyPrefix = keyof typeof document.vocabularies; /** * Strength of a mapping, using SKOS mapping relations so the table is itself * expressible as RDF. * * `noMatch` is not the absence of an entry. It is a deliberate statement that * no external term should be used for this concept, and it carries a reason. */ type MatchStrength = 'exactMatch' | 'closeMatch' | 'broadMatch' | 'narrowMatch' | 'relatedMatch' | 'noMatch'; interface TermMapping { /** Lexicon NSID, e.g. `id.sifa.profile.presentation`. */ readonly lexicon: string; /** * Field name within the record. Omitted for a record-level class mapping * (what the record *is*, rather than what one of its fields means). */ readonly field?: string; /** CURIEs, e.g. `dcterms:title`. Empty when `match` is `noMatch`. */ readonly terms: readonly string[]; readonly match: MatchStrength; /** Rationale. Always present when `match` is `noMatch`. */ readonly note?: string; } /** * Every reconciliation Sifa asserts, including the deliberate non-mappings. * * The published document splits these into `mappings` and `unmapped`, which * reads better over the wire. Callers here want one list, so they are * flattened back together. */ declare const TERM_MAPPINGS: readonly TermMapping[]; /** * Expand a CURIE (`dcterms:title`) to a full IRI. Returns null for an unknown * prefix rather than guessing a namespace. */ declare function expandCurie(curie: string): string | null; /** All mappings declared for one lexicon NSID, record level and field level. */ declare function mappingsForLexicon(nsid: string): readonly TermMapping[]; /** True when Sifa has deliberately declined to map this lexicon or field. */ declare function isDeliberatelyUnmapped(nsid: string, field?: string): boolean; /** * Schema.org JSON-LD for a Sifa profile. * * Ported from sifa-web's `src/lib/jsonld.ts` so that sifa.id, page.sifa.id and * any future consumer emit the same graph from one implementation. Term choices * are recorded in `./terms.js`. * * These are pure functions: no fetching, no DOM, no framework. */ type Sanitizer = (input: string) => string; interface JsonLdOptions { /** Canonical origin for profile URLs. Defaults to `https://sifa.id`. */ readonly baseUrl?: string; /** Applied to every user-authored string. Defaults to identity. */ readonly sanitize?: Sanitizer; /** * Absolute URL of the page this graph describes, used for `url` and `@id`. * Defaults to `${baseUrl}/p/${handle}`. Personal sites can be served from an * arbitrary host, including a self-hosted custom domain, where that default * path is not where the page lives. */ readonly canonicalUrl?: string; } /** * Structural input for the emitters. * * Deliberately looser than `Profile`: it accepts a `Profile` unchanged, but * also the partial shapes held by consumers that render a subset (page.sifa.id) * without forcing them to fabricate required fields. */ interface JsonLdProfileInput { readonly handle: string; readonly displayName?: string; readonly givenName?: string; readonly familyName?: string; readonly headline?: string; readonly about?: string; readonly avatar?: string; readonly website?: string; readonly location?: LocationValue | null; readonly updatedAt?: string; readonly positions?: readonly JsonLdPosition[]; readonly education?: readonly JsonLdEducation[]; readonly skills?: readonly JsonLdSkill[]; readonly certifications?: readonly JsonLdCertification[]; readonly volunteering?: readonly JsonLdVolunteering[]; readonly honors?: readonly JsonLdHonor[]; readonly languages?: readonly JsonLdLanguage[]; readonly verifiedAccounts?: readonly { platform: string; identifier: string; url?: string; }[]; readonly activeApps?: readonly { id: string; }[]; /** Only the length is read, to decide which section anchors to advertise. */ readonly projects?: readonly unknown[]; readonly publications?: readonly unknown[]; readonly courses?: readonly unknown[]; readonly externalAccounts?: readonly unknown[]; /** * Dual-facet accounts: one DID presenting as both a person and a company. * Only the opted-in case is emitted, see `buildPersonJsonLd`. */ readonly org?: { readonly personalProfileVisible?: boolean; readonly orgProfile?: { readonly name?: string; } | null; } | null; } interface Hideable { readonly hidden?: boolean; } interface JsonLdPosition extends Hideable { readonly company?: string; /** * Current canonical name of the linked company entity, resolved by the * AppView at read time. Preferred over the free-text `company` snapshot for * `worksFor.name` so structured data names the corrected (and decoded) entity. */ readonly entityName?: string; readonly title?: string; readonly startedAt?: string; readonly endedAt?: string; readonly description?: string; readonly primary?: boolean; } interface JsonLdEducation extends Hideable { readonly institution?: string; readonly degree?: string; readonly fieldOfStudy?: string; } interface JsonLdSkill extends Hideable { readonly name?: string; readonly endorsementCount?: number; } interface JsonLdCertification extends Hideable { readonly name?: string; readonly authority?: string; readonly issuingOrg?: string; readonly credentialUrl?: string; } interface JsonLdVolunteering extends Hideable { readonly organization?: string; readonly role?: string; readonly startDate?: string; readonly endDate?: string; } interface JsonLdHonor extends Hideable { readonly title?: string; } interface JsonLdLanguage extends Hideable { readonly language?: string; } declare function buildPersonJsonLd(profile: JsonLdProfileInput, options?: JsonLdOptions): { sameAs?: string[] | undefined; knowsAbout?: string[] | undefined; knowsLanguage?: string[] | undefined; award?: string[] | undefined; memberOf?: { endDate?: string | undefined; startDate?: string | undefined; roleName?: string | undefined; '@type': "OrganizationRole"; memberOf: { '@type': "Organization"; name: string; }; }[] | undefined; hasCredential?: ({ recognizedBy?: { '@type': "EducationalOrganization"; name: string; } | undefined; '@type': "EducationalOccupationalCredential"; credentialCategory: "degree"; name: string; } | { url?: string | undefined; recognizedBy?: { '@type': "Organization"; name: string; } | undefined; '@type': "EducationalOccupationalCredential"; name: string; })[] | undefined; alumniOf?: { '@type': "EducationalOrganization"; name: string; }[] | undefined; worksFor?: ({ '@type': "Organization"; '@id': string; name: string; } | { member?: { endDate?: string | undefined; startDate?: string | undefined; '@type': "OrganizationRole"; roleName: string; } | undefined; '@type': "Organization"; name: string; })[] | undefined; homeLocation?: { address?: { addressCountry?: string | undefined; addressLocality?: string | undefined; '@type': "PostalAddress"; } | undefined; '@type': "Place"; name: string; } | undefined; jobTitle: string | undefined; description: string | undefined; alternateName: string; url: string; image: string | undefined; familyName?: string | undefined; givenName?: string | undefined; '@context': string; '@type': string; '@id': string; name: string; }; declare function buildProfilePageJsonLd(profile: JsonLdProfileInput, options?: JsonLdOptions): { hasPart?: { '@type': "WebPageElement"; name: string; url: string; }[] | undefined; mainEntity: { sameAs?: string[] | undefined; knowsAbout?: string[] | undefined; knowsLanguage?: string[] | undefined; award?: string[] | undefined; memberOf?: { endDate?: string | undefined; startDate?: string | undefined; roleName?: string | undefined; '@type': "OrganizationRole"; memberOf: { '@type': "Organization"; name: string; }; }[] | undefined; hasCredential?: ({ recognizedBy?: { '@type': "EducationalOrganization"; name: string; } | undefined; '@type': "EducationalOccupationalCredential"; credentialCategory: "degree"; name: string; } | { url?: string | undefined; recognizedBy?: { '@type': "Organization"; name: string; } | undefined; '@type': "EducationalOccupationalCredential"; name: string; })[] | undefined; alumniOf?: { '@type': "EducationalOrganization"; name: string; }[] | undefined; worksFor?: ({ '@type': "Organization"; '@id': string; name: string; } | { member?: { endDate?: string | undefined; startDate?: string | undefined; '@type': "OrganizationRole"; roleName: string; } | undefined; '@type': "Organization"; name: string; })[] | undefined; homeLocation?: { address?: { addressCountry?: string | undefined; addressLocality?: string | undefined; '@type': "PostalAddress"; } | undefined; '@type': "Place"; name: string; } | undefined; jobTitle: string | undefined; description: string | undefined; alternateName: string; url: string; image: string | undefined; familyName?: string | undefined; givenName?: string | undefined; '@type': string; '@id': string; name: string; }; dateModified?: string | undefined; '@context': string; '@type': "ProfilePage"; url: string; }; declare function buildBreadcrumbListJsonLd(profile: Pick, options?: JsonLdOptions): { '@context': string; '@type': "BreadcrumbList"; itemListElement: { '@type': "ListItem"; position: number; name: string; item: string; }[]; }; /** * Schema.org JSON-LD for the things a person made: talks, publications, * courses and projects. * * These collections carried no structured data before this module existed; * a talk page emitted a four-property `CreativeWork` and publications, * courses and projects emitted nothing at all. Term choices are recorded in * `./terms.js`. */ interface WorksOptions { readonly baseUrl?: string; readonly sanitize?: (input: string) => string; } /** Minimal identity for the profile owner a work is attributed to. */ interface WorkAuthor { readonly handle: string; readonly displayName?: string; } /** * A person named on somebody else's record. `confirmed` is load bearing: an * unconfirmed claim is a claim, not a fact, and must never be laundered into * structured data as a schema.org Person. */ interface NamedActor { readonly did?: string; readonly handle?: string; readonly displayName?: string; readonly confirmed?: boolean; } interface PersonNode { readonly '@type': 'Person'; readonly name: string; readonly url?: string; readonly sameAs?: string[]; } interface PresentationLinkInput { readonly uri: string; readonly label?: string; readonly type?: string; } interface PresentationDeliveryInput { readonly rkey: string; readonly title?: string | null; readonly role?: string | null; readonly eventName?: string | null; readonly date?: string | null; readonly location?: string | null; readonly locationLocality?: string | null; readonly locationRegion?: string | null; readonly countryCode?: string | null; readonly mode?: string | null; readonly status?: string | null; readonly links?: readonly PresentationLinkInput[]; readonly coSpeakers?: readonly NamedActor[]; readonly hidden?: boolean; } interface PresentationInput { readonly rkey: string; readonly title: string; readonly description?: string | null; readonly duration?: { minMinutes: number; maxMinutes?: number; } | null; readonly coverImageUrl?: string | null; readonly links?: readonly PresentationLinkInput[]; readonly deliveries?: readonly PresentationDeliveryInput[]; readonly hidden?: boolean; } declare function buildPresentationJsonLd(presentation: PresentationInput, author: WorkAuthor, options?: WorksOptions): { subjectOf?: { workFeatured?: { '@type': "PresentationDigitalDocument"; url: string; } | undefined; recordedIn?: { '@type': "VideoObject"; url: string; } | undefined; performer: PersonNode[]; eventStatus?: string | undefined; eventAttendanceMode?: string | undefined; location?: { '@type': "Place"; address: { addressCountry?: string | undefined; addressRegion?: string | undefined; addressLocality?: string | undefined; '@type': "PostalAddress"; }; name?: undefined; } | { '@type': "Place"; name: string; address?: undefined; } | undefined; startDate?: string | undefined; '@type': "Event"; name: string; }[] | undefined; author: PersonNode; url: string; image?: string | undefined; timeRequired?: string | undefined; abstract?: string | undefined; '@context': string; '@type': "PresentationDigitalDocument"; name: string; }; interface PublicationContributorInput { readonly name: string; readonly orcidId?: string; readonly handle?: string; } interface PublicationInput { readonly rkey: string; readonly title: string; readonly subtitle?: string; readonly publisher?: string; readonly date?: string; readonly url?: string; readonly description?: string; readonly doi?: string; readonly contributors?: readonly PublicationContributorInput[]; readonly hidden?: boolean; } declare function buildPublicationJsonLd(publication: PublicationInput, author: WorkAuthor, options?: WorksOptions): { identifier?: { '@type': "PropertyValue"; propertyID: string; value: string; } | undefined; sameAs?: string[] | undefined; author: PersonNode[]; url?: string | undefined; datePublished?: string | undefined; publisher?: { '@type': "Organization"; name: string; } | undefined; abstract?: string | undefined; alternativeHeadline?: string | undefined; '@context': string; '@type': "ScholarlyArticle"; name: string; }; interface CourseInput { readonly rkey: string; readonly name: string; readonly number?: string; readonly institution?: string; readonly hidden?: boolean; } declare function buildCourseJsonLd(course: CourseInput, options?: WorksOptions): { provider?: { '@type': "EducationalOrganization"; name: string; } | undefined; courseCode?: string | undefined; '@context': string; '@type': "Course"; name: string; }; interface ProjectInput { readonly rkey: string; readonly name: string; readonly description?: string; readonly url?: string; readonly startDate?: string; readonly endDate?: string; readonly members?: readonly NamedActor[]; readonly hidden?: boolean; } declare function buildProjectJsonLd(project: ProjectInput, author: WorkAuthor, options?: WorksOptions): { member: PersonNode[]; endDate?: string | undefined; startDate?: string | undefined; url?: string | undefined; description?: string | undefined; '@context': string; '@type': "Project"; name: string; }; /** * The works on a profile as one JSON-LD `@graph`. * * A profile page already emits a `ProfilePage` whose `mainEntity` is the * Person. Publications, talks, courses and projects are separate entities * rather than properties of that Person, so they go in their own block and * point back at the Person by `@id` instead of repeating the whole node. */ interface ProfileWorksInput { readonly handle: string; readonly publications?: readonly PublicationInput[]; readonly presentations?: readonly PresentationInput[]; readonly courses?: readonly CourseInput[]; readonly projects?: readonly ProjectInput[]; } /** * Returns null when there is nothing to say, so a caller can skip the script * block entirely rather than emitting an empty graph. */ declare function buildProfileWorksJsonLd(profile: ProfileWorksInput, author: WorkAuthor, options?: JsonLdOptions): { '@context': string; '@graph': Record[]; } | null; export { type CourseInput, type JsonLdCertification, type JsonLdEducation, type JsonLdHonor, type JsonLdLanguage, type JsonLdOptions, type JsonLdPosition, type JsonLdProfileInput, type JsonLdSkill, type JsonLdVolunteering, type MatchStrength, type PresentationDeliveryInput, type PresentationInput, type PresentationLinkInput, type ProfileWorksInput, type ProjectInput, type PublicationContributorInput, type PublicationInput, type Sanitizer, TERM_MAPPINGS, type TermMapping, VOCABULARIES, type VocabularyPrefix, type WorkAuthor, type WorksOptions, buildBreadcrumbListJsonLd, buildCourseJsonLd, buildPersonJsonLd, buildPresentationJsonLd, buildProfilePageJsonLd, buildProfileWorksJsonLd, buildProjectJsonLd, buildPublicationJsonLd, expandCurie, isDeliberatelyUnmapped, mappingsForLexicon };