@singi-labs/sifa-sdk 0.11.3 → 0.11.5

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.
@@ -174,6 +174,49 @@ interface ProfileCourse {
174
174
  credentialRkey?: string;
175
175
  hidden?: boolean;
176
176
  }
177
+ /** A related link on a presentation or delivery, as returned by the AppView. */
178
+ interface PresentationLinkView {
179
+ uri: string;
180
+ label?: string;
181
+ type?: string;
182
+ }
183
+ /** An occasion on which a presentation was delivered (the AppView view-model). */
184
+ interface ProfilePresentationDelivery {
185
+ rkey: string;
186
+ /** rkey of the parent presentation when this delivery references one. */
187
+ presentationRkey?: string | null;
188
+ title?: string | null;
189
+ role?: string | null;
190
+ eventName?: string | null;
191
+ /** Day-only date, YYYY-MM-DD. */
192
+ date?: string | null;
193
+ location?: string | null;
194
+ /** Full community.lexicon.calendar.event mode token. */
195
+ mode?: string | null;
196
+ /** Full community.lexicon.calendar.event status token. */
197
+ status?: string | null;
198
+ links?: PresentationLinkView[];
199
+ /** at-uri of the linked calendar event, when present. */
200
+ eventUri?: string | null;
201
+ hidden?: boolean;
202
+ }
203
+ /** A reusable presentation with its deliveries grouped underneath (AppView view-model). */
204
+ interface ProfilePresentation {
205
+ rkey: string;
206
+ title: string;
207
+ description?: string | null;
208
+ /** Duration in minutes: a fixed value (min only) or a range. */
209
+ duration?: {
210
+ minMinutes: number;
211
+ maxMinutes?: number;
212
+ } | null;
213
+ intendedAudiences?: string[];
214
+ links?: PresentationLinkView[];
215
+ /** at-uri of a long-form write-up (Leaflet / site.standard document). */
216
+ writeupUri?: string | null;
217
+ hidden?: boolean;
218
+ deliveries?: ProfilePresentationDelivery[];
219
+ }
177
220
  interface TrustStat {
178
221
  key: string;
179
222
  label: string;
@@ -319,6 +362,8 @@ interface Profile {
319
362
  honors?: ProfileHonor[];
320
363
  languages?: ProfileLanguage[];
321
364
  courses?: ProfileCourse[];
365
+ presentations?: ProfilePresentation[];
366
+ presentationDeliveries?: ProfilePresentationDelivery[];
322
367
  externalAccounts?: ExternalAccount[];
323
368
  }
324
369
 
@@ -361,4 +406,4 @@ declare function hasAdultContent(item: {
361
406
  labels?: ActivityLabel[];
362
407
  }): boolean;
363
408
 
364
- export { type AdultContentLabel as A, type ExternalAccount as E, type FeedItem as F, type LocationValue as L, type ProfileSkill as P, type SkillSuggestion as S, type TrustStat as T, type VerifiedAccount as V, type ActivityLabel as a, type PdsProviderInfo as b, type Profile as c, ADULT_CONTENT_LABELS as d, type ActiveApp as e, type Endorsement as f, type EndorsementData as g, type ExternalAccountKeytraceClaim as h, type LanguageProficiency as i, type ProfileCertification as j, type ProfileCourse as k, type ProfileEducation as l, type ProfileHonor as m, type ProfileIndustry as n, type ProfileLanguage as o, type ProfileLocation as p, type ProfileOverrideSource as q, type ProfilePosition as r, type ProfileProject as s, type ProfilePublication as t, type ProfileVolunteering as u, type PublicationContributor as v, type SkillRef as w, hasAdultContent as x };
409
+ export { type AdultContentLabel as A, hasAdultContent as B, type ExternalAccount as E, type FeedItem as F, type LocationValue as L, type ProfileSkill as P, type SkillSuggestion as S, type TrustStat as T, type VerifiedAccount as V, type ActivityLabel as a, type PdsProviderInfo as b, type Profile as c, ADULT_CONTENT_LABELS as d, type ActiveApp as e, type Endorsement as f, type EndorsementData as g, type ExternalAccountKeytraceClaim as h, type LanguageProficiency as i, type PresentationLinkView as j, type ProfileCertification as k, type ProfileCourse as l, type ProfileEducation as m, type ProfileHonor as n, type ProfileIndustry as o, type ProfileLanguage as p, type ProfileLocation as q, type ProfileOverrideSource as r, type ProfilePosition as s, type ProfilePresentation as t, type ProfilePresentationDelivery as u, type ProfileProject as v, type ProfilePublication as w, type ProfileVolunteering as x, type PublicationContributor as y, type SkillRef as z };
@@ -174,6 +174,49 @@ interface ProfileCourse {
174
174
  credentialRkey?: string;
175
175
  hidden?: boolean;
176
176
  }
177
+ /** A related link on a presentation or delivery, as returned by the AppView. */
178
+ interface PresentationLinkView {
179
+ uri: string;
180
+ label?: string;
181
+ type?: string;
182
+ }
183
+ /** An occasion on which a presentation was delivered (the AppView view-model). */
184
+ interface ProfilePresentationDelivery {
185
+ rkey: string;
186
+ /** rkey of the parent presentation when this delivery references one. */
187
+ presentationRkey?: string | null;
188
+ title?: string | null;
189
+ role?: string | null;
190
+ eventName?: string | null;
191
+ /** Day-only date, YYYY-MM-DD. */
192
+ date?: string | null;
193
+ location?: string | null;
194
+ /** Full community.lexicon.calendar.event mode token. */
195
+ mode?: string | null;
196
+ /** Full community.lexicon.calendar.event status token. */
197
+ status?: string | null;
198
+ links?: PresentationLinkView[];
199
+ /** at-uri of the linked calendar event, when present. */
200
+ eventUri?: string | null;
201
+ hidden?: boolean;
202
+ }
203
+ /** A reusable presentation with its deliveries grouped underneath (AppView view-model). */
204
+ interface ProfilePresentation {
205
+ rkey: string;
206
+ title: string;
207
+ description?: string | null;
208
+ /** Duration in minutes: a fixed value (min only) or a range. */
209
+ duration?: {
210
+ minMinutes: number;
211
+ maxMinutes?: number;
212
+ } | null;
213
+ intendedAudiences?: string[];
214
+ links?: PresentationLinkView[];
215
+ /** at-uri of a long-form write-up (Leaflet / site.standard document). */
216
+ writeupUri?: string | null;
217
+ hidden?: boolean;
218
+ deliveries?: ProfilePresentationDelivery[];
219
+ }
177
220
  interface TrustStat {
178
221
  key: string;
179
222
  label: string;
@@ -319,6 +362,8 @@ interface Profile {
319
362
  honors?: ProfileHonor[];
320
363
  languages?: ProfileLanguage[];
321
364
  courses?: ProfileCourse[];
365
+ presentations?: ProfilePresentation[];
366
+ presentationDeliveries?: ProfilePresentationDelivery[];
322
367
  externalAccounts?: ExternalAccount[];
323
368
  }
324
369
 
@@ -361,4 +406,4 @@ declare function hasAdultContent(item: {
361
406
  labels?: ActivityLabel[];
362
407
  }): boolean;
363
408
 
364
- export { type AdultContentLabel as A, type ExternalAccount as E, type FeedItem as F, type LocationValue as L, type ProfileSkill as P, type SkillSuggestion as S, type TrustStat as T, type VerifiedAccount as V, type ActivityLabel as a, type PdsProviderInfo as b, type Profile as c, ADULT_CONTENT_LABELS as d, type ActiveApp as e, type Endorsement as f, type EndorsementData as g, type ExternalAccountKeytraceClaim as h, type LanguageProficiency as i, type ProfileCertification as j, type ProfileCourse as k, type ProfileEducation as l, type ProfileHonor as m, type ProfileIndustry as n, type ProfileLanguage as o, type ProfileLocation as p, type ProfileOverrideSource as q, type ProfilePosition as r, type ProfileProject as s, type ProfilePublication as t, type ProfileVolunteering as u, type PublicationContributor as v, type SkillRef as w, hasAdultContent as x };
409
+ export { type AdultContentLabel as A, hasAdultContent as B, type ExternalAccount as E, type FeedItem as F, type LocationValue as L, type ProfileSkill as P, type SkillSuggestion as S, type TrustStat as T, type VerifiedAccount as V, type ActivityLabel as a, type PdsProviderInfo as b, type Profile as c, ADULT_CONTENT_LABELS as d, type ActiveApp as e, type Endorsement as f, type EndorsementData as g, type ExternalAccountKeytraceClaim as h, type LanguageProficiency as i, type PresentationLinkView as j, type ProfileCertification as k, type ProfileCourse as l, type ProfileEducation as m, type ProfileHonor as n, type ProfileIndustry as o, type ProfileLanguage as p, type ProfileLocation as q, type ProfileOverrideSource as r, type ProfilePosition as s, type ProfilePresentation as t, type ProfilePresentationDelivery as u, type ProfileProject as v, type ProfilePublication as w, type ProfileVolunteering as x, type PublicationContributor as y, type SkillRef as z };
package/dist/index.cjs CHANGED
@@ -1404,6 +1404,16 @@ function formatRelativeTime(dateString) {
1404
1404
  return `${years}y ago`;
1405
1405
  }
1406
1406
 
1407
+ // src/format/format-duration.ts
1408
+ function formatPresentationDuration(duration) {
1409
+ if (!duration) return void 0;
1410
+ const { minMinutes, maxMinutes } = duration;
1411
+ if (maxMinutes != null && maxMinutes !== minMinutes) {
1412
+ return `${minMinutes}-${maxMinutes} min`;
1413
+ }
1414
+ return `${minMinutes} min`;
1415
+ }
1416
+
1407
1417
  // src/format/sort-by-date.ts
1408
1418
  var FAR_FUTURE = "9999-12-31";
1409
1419
  var FAR_PAST = "0000-01-01";
@@ -1627,6 +1637,102 @@ function meetsContrastAA(foreground, background) {
1627
1637
  return contrastRatio(foreground, background) >= 4.5;
1628
1638
  }
1629
1639
 
1640
+ // src/import/presentation-csv.ts
1641
+ function clean(value) {
1642
+ return (value ?? "").trim();
1643
+ }
1644
+ function parsePresentationDuration(input) {
1645
+ const numbers = (clean(input).match(/\d+/g) ?? []).map((n) => Number.parseInt(n, 10)).filter((n) => Number.isInteger(n) && n > 0);
1646
+ const min = numbers.at(0);
1647
+ if (min === void 0) return void 0;
1648
+ const max = numbers.at(1);
1649
+ return max !== void 0 && max >= min ? { minMinutes: min, maxMinutes: max } : { minMinutes: min };
1650
+ }
1651
+ function durationFromMinutes(minRaw, maxRaw) {
1652
+ const min = Number.parseInt(clean(minRaw), 10);
1653
+ if (!Number.isInteger(min) || min < 1) return void 0;
1654
+ const max = Number.parseInt(clean(maxRaw), 10);
1655
+ return Number.isInteger(max) && max >= min ? { minMinutes: min, maxMinutes: max } : { minMinutes: min };
1656
+ }
1657
+ function parseIntendedAudiences(input, delimiter = ";") {
1658
+ return clean(input).split(delimiter).map((s) => s.trim()).filter(Boolean);
1659
+ }
1660
+ function stripHtmlToText(input) {
1661
+ const text = clean(input).replace(/<\s*br\s*\/?>/gi, "\n").replace(/<\/\s*(p|div|li|h[1-6])\s*>/gi, "\n").replace(/<[^>]*>/g, "").replace(/&nbsp;/gi, " ").replace(/&amp;/gi, "&").replace(/&lt;/gi, "<").replace(/&gt;/gi, ">").replace(/&quot;/gi, '"').replace(/&#0*39;|&apos;/gi, "'");
1662
+ return text.replace(/[ \t]+/g, " ").replace(/ *\n */g, "\n").replace(/\n{3,}/g, "\n\n").trim();
1663
+ }
1664
+ var ROLE_TOKENS = {
1665
+ presenter: "id.sifa.defs#presenter",
1666
+ speaker: "id.sifa.defs#presenter",
1667
+ panelist: "id.sifa.defs#panelist",
1668
+ keynote: "id.sifa.defs#keynote",
1669
+ workshop: "id.sifa.defs#workshop",
1670
+ host: "id.sifa.defs#host"
1671
+ };
1672
+ function normalizePresentationRole(value) {
1673
+ const v = clean(value).toLowerCase();
1674
+ if (!v) return void 0;
1675
+ if (v.startsWith("id.sifa.defs#")) return v;
1676
+ return ROLE_TOKENS[v] ?? v;
1677
+ }
1678
+ var MODE_FRAGMENTS = {
1679
+ inperson: "#inperson",
1680
+ "in person": "#inperson",
1681
+ "in-person": "#inperson",
1682
+ virtual: "#virtual",
1683
+ online: "#virtual",
1684
+ remote: "#virtual",
1685
+ hybrid: "#hybrid"
1686
+ };
1687
+ function normalizePresentationMode(value) {
1688
+ const v = clean(value).toLowerCase();
1689
+ if (!v) return void 0;
1690
+ if (v.startsWith("community.lexicon.calendar.event#")) return v;
1691
+ const fragment = MODE_FRAGMENTS[v];
1692
+ return fragment ? `community.lexicon.calendar.event${fragment}` : void 0;
1693
+ }
1694
+ function link(uri, type) {
1695
+ const u = clean(uri);
1696
+ return u ? { uri: u, type } : void 0;
1697
+ }
1698
+ function presentationCsvRowToRecord(row) {
1699
+ const description = stripHtmlToText(row.description);
1700
+ const duration = parsePresentationDuration(row.duration) ?? durationFromMinutes(row.duration_min_minutes, row.duration_max_minutes);
1701
+ const intendedAudiences = parseIntendedAudiences(row.intended_audiences);
1702
+ const links = [
1703
+ link(row.slides_url, "id.sifa.defs#linkSlides"),
1704
+ link(row.recording_url, "id.sifa.defs#linkRecording"),
1705
+ link(row.writeup_url, "id.sifa.defs#linkWriteup")
1706
+ ].filter((l) => l !== void 0);
1707
+ const record = { title: clean(row.title) };
1708
+ if (description) record.description = description;
1709
+ if (duration) record.duration = duration;
1710
+ if (intendedAudiences.length) record.intendedAudiences = intendedAudiences;
1711
+ if (links.length) record.links = links;
1712
+ return { key: clean(row.presentation_key) || void 0, record };
1713
+ }
1714
+ function presentationDeliveryCsvRowToRecord(row) {
1715
+ const links = [
1716
+ link(row.event_url, "id.sifa.defs#linkEvent"),
1717
+ link(row.recording_url, "id.sifa.defs#linkRecording")
1718
+ ].filter((l) => l !== void 0);
1719
+ const record = {};
1720
+ const title = clean(row.title);
1721
+ const eventName = clean(row.event_name);
1722
+ const date = clean(row.date);
1723
+ const location = clean(row.location);
1724
+ const role = normalizePresentationRole(row.role);
1725
+ const mode = normalizePresentationMode(row.mode);
1726
+ if (title) record.title = title;
1727
+ if (role) record.role = role;
1728
+ if (eventName) record.eventName = eventName;
1729
+ if (date) record.date = date;
1730
+ if (location) record.location = location;
1731
+ if (mode) record.mode = mode;
1732
+ if (links.length) record.links = links;
1733
+ return { presentationKey: clean(row.presentation_key) || void 0, record };
1734
+ }
1735
+
1630
1736
  // src/cards/app-url-patterns.ts
1631
1737
  var APP_URL_PATTERNS = Object.freeze({
1632
1738
  bluesky: {
@@ -2444,7 +2550,7 @@ var ProfileVolunteeringRecordSchema = zod.z.object({
2444
2550
  });
2445
2551
 
2446
2552
  // src/index.ts
2447
- var SIFA_SDK_VERSION = "0.11.3";
2553
+ var SIFA_SDK_VERSION = "0.11.5";
2448
2554
 
2449
2555
  exports.ACTIVITY_TIERS = ACTIVITY_TIERS;
2450
2556
  exports.ACTIVITY_VISIBILITY_RULES = ACTIVITY_VISIBILITY_RULES;
@@ -2528,11 +2634,13 @@ exports.dedupeSkills = dedupeSkills;
2528
2634
  exports.detectPdsProvider = detectPdsProvider;
2529
2635
  exports.didSchema = didSchema;
2530
2636
  exports.dimensionsFromInputs = dimensionsFromInputs;
2637
+ exports.durationFromMinutes = durationFromMinutes;
2531
2638
  exports.encodeFeedCursor = encodeFeedCursor;
2532
2639
  exports.externalRecordRefSchema = externalRecordRefSchema;
2533
2640
  exports.findIndustry = findIndustry;
2534
2641
  exports.formatDistanceToNow = formatDistanceToNow;
2535
2642
  exports.formatLocation = formatLocation;
2643
+ exports.formatPresentationDuration = formatPresentationDuration;
2536
2644
  exports.formatRelativeTime = formatRelativeTime;
2537
2645
  exports.getActivityTaxonomyVersion = getActivityTaxonomyVersion;
2538
2646
  exports.getActivityTier = getActivityTier;
@@ -2574,12 +2682,18 @@ exports.maxGraphemes = maxGraphemes;
2574
2682
  exports.meetsContrastAA = meetsContrastAA;
2575
2683
  exports.normalizeOpenTo = normalizeOpenTo;
2576
2684
  exports.normalizePlatformId = normalizePlatformId;
2685
+ exports.normalizePresentationMode = normalizePresentationMode;
2686
+ exports.normalizePresentationRole = normalizePresentationRole;
2577
2687
  exports.normalizeWorkplaceTypes = normalizeWorkplaceTypes;
2578
2688
  exports.openToTokenToValue = openToTokenToValue;
2579
2689
  exports.openToValueToToken = openToValueToToken;
2690
+ exports.parseIntendedAudiences = parseIntendedAudiences;
2580
2691
  exports.parseLocationString = parseLocationString;
2692
+ exports.parsePresentationDuration = parsePresentationDuration;
2581
2693
  exports.pdsProviderFromApi = pdsProviderFromApi;
2582
2694
  exports.pickPrimaryPosition = pickPrimaryPosition;
2695
+ exports.presentationCsvRowToRecord = presentationCsvRowToRecord;
2696
+ exports.presentationDeliveryCsvRowToRecord = presentationDeliveryCsvRowToRecord;
2583
2697
  exports.profileToDimensionInputs = profileToDimensionInputs;
2584
2698
  exports.relativeLuminance = relativeLuminance;
2585
2699
  exports.resolveCardUrl = resolveCardUrl;
@@ -2589,6 +2703,7 @@ exports.sanitizeHandleInput = sanitizeHandleInput;
2589
2703
  exports.selfLabelsSchema = selfLabelsSchema;
2590
2704
  exports.singleDateExtractor = singleDateExtractor;
2591
2705
  exports.sortByDateDesc = sortByDateDesc;
2706
+ exports.stripHtmlToText = stripHtmlToText;
2592
2707
  exports.strongRefSchema = strongRefSchema;
2593
2708
  exports.truncateGraphemes = truncateGraphemes;
2594
2709
  exports.uriSchema = uriSchema;