@odla-ai/chapter 0.32.0 → 0.32.2

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/dist/index.d.cts CHANGED
@@ -1921,4 +1921,27 @@ declare function validateMembershipPageDocument(input: unknown, options?: Member
1921
1921
  /** Validate a document or fail closed with all actionable validation errors. */
1922
1922
  declare function membershipPageDocument(input: unknown, options?: MembershipPageValidationOptions): MembershipPageDocument;
1923
1923
 
1924
- export { type AccountModel, type AdminNotificationTrigger, type Applicant, type ApplicationBookingPatch, type ApplicationRecord, type ApplicationSummary, type Attr, type AttrType, type Chapter, type ChapterApplication, type ChapterAuth, type ChapterBrand, type ChapterConfig, type ChapterCopy, type ChapterCopyInput, type ChapterDb, type ChapterEmails, type ChapterIntegrationDescriptor, type ChapterIntegrationOptions, type ChapterMode, type ChapterNetwork, type ChapterNetworkReader, type ChapterNetworkTarget, type ChapterOperations, type ChapterPipeline, type ChapterPolicy, type ChapterPrices, type ChapterRunbookHints, type ChapterScheduling, type ChapterSends, type ChapterTier, type ChapterTierConfig, type ClerkInviteInput, type ClerkMetadataInput, type ClerkResult, type ClerkUserInput, type ClerkUserRecord, type CompiledChapterBrandTokens, DEFAULT_CHAPTER_COPY, DEFAULT_SHARE_FIELDS, type DashboardMetricData, type DashboardMetricSeries, type DbOp, type DbRules, type DbSchema, type DeliveryDecision, type EmailGroup, type EmailTemplate, type EmailTemplateRow, type Entity, type ExistingMeeting, type GuardResult, type IntegrationDescriptor, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type IntegrationSync, type JoinConfigGroup, type JoinConfigTier, type LeaderCrmOptions, type LeaderFormationConfig, type LiveEvent, MEMBERSHIP_PAGE_RENDERER, type MailSender, type MeetingForReconcile, type MeetingRecord, type MeetingReschedulePatch, type MemberApplication, type MemberSession, type MembershipPageDocument, type MembershipPageValidationOptions, type MembershipPageValidationResult, type MembershipTierAuthority, type MembershipTierCallout, type MembershipTierCapacity, type MembershipTierPresentation, type MembershipTierVariant, type NetworkRecord, type NetworkRecordNote, type NetworkRecordPage, type NetworkRollup, type NetworkRollupTarget, type NetworkSharedNote, type NetworkSnapshot, type NewMeetingRow, type NotifyDeps, type NotifyInput, type NotifyResult, type PaymentsGroup, type ProjectionDeps, type ReconcileDecision, type ResolvedApplication, type ResolvedAuth, type ResolvedLeaderFormation, type ResolvedNetwork, type ResolvedNetworkReader, type ResolvedNetworkTarget, type ResolvedOperations, type ResolvedPipeline, type ResolvedScheduling, type ResolvedSends, type RoleChangeContext, type Rule, SCHEDULING_DEFAULTS, type SchedulingErrors, type SecretMode, type SecretStore, type SessionUser, type SharedBusiness, type SharedPerson, type SharedRecord, type SharedRecordV1, type SharedRecordV2, type StripeEvent, type StripeResult, type SubmitResult, type TierGroup, type TierGroupRow, type WebhookEvent, applicantProfile, applicationBookingUpdate, applicationSummary, backfillCrm, bookingDecision, brandTokens, bucketSeries, buildGroupSeed, buildTierSeeds, canApprove, canBook, canChangeRole, canTransition, canceledPatch, chapterBrandFromTokens, chapterDb, clampArray, clerkGetUser, clerkGetUserByEmail, clerkIntegration, clerkInviteRequest, clerkListUsers, clerkSetRole, clerkUserRequest, createChapterIntegration, createClerkInvitation, createClerkUser, dashboardMetricData, defaultCrm, defineChapter, emailGroupFrom, endForSlot, findApplicationRef, findTier, firstPaymentPatch, formatChapterCopy, formationFields, getVaultSecret, hasDisclaimerAck, introIdempotencyKey, isAdminRole, isAlreadySent, isReconcilable, isSlotAvailable, isValidEmail, joinConfig, joinConfigTiers, leaderCrmConfig, loadOfferableTiers, loadTiers, meetingCreateRow, meetingRescheduleUpdate, memberApplication, memberSession, membershipPageDocument, networkSourceTag, normalizeSharedRecord, normalizeWebhookEvent, offerableTiers, paymentsReady, personInputFromApp, planDelivery, projectApplicant, projectSharedRecord, reconcileMeetings, refundedPatch, render, renderSummary, renderTemplateBody, renewalPatch, resolveApplication, resolveAuth, resolveChapterCopy, resolveLeaderFormation, resolvePipeline, resolveScheduling, resolveTiers, roleFromClaim, sendTemplated, sharedPersonInput, sharedRecordFromCrm, slotWindow, stageIndex, stripeCall, subAnnualCents, submitApplication, subscriptionIdempotencyKey, syncApplicationToCrm, tierIsFree, tierPayable, updateClerkUserMetadata, updateClerkUserMetadataByEmail, validateMembershipPageDocument, validateScheduling, webhookMutationId };
1924
+ /** A presentation overlay parsed from the constrained membership Markdown convention. */
1925
+ type MembershipTierMarkdownResult = {
1926
+ ok: true;
1927
+ value: MembershipTierPresentation;
1928
+ } | {
1929
+ ok: false;
1930
+ errors: readonly string[];
1931
+ };
1932
+ /**
1933
+ * Apply authored Markdown to the text slots of an existing tier presentation.
1934
+ *
1935
+ * The convention is deliberately small and reviewable:
1936
+ * - prelude prose -> summary; prelude bullets -> benefits
1937
+ * - `## Summary`, `## Benefits`, `## Price note`, `## Callout: Label`,
1938
+ * and `## Action` target those exact renderer slots
1939
+ *
1940
+ * Identity, price, scarcity, variants, badges, links, HTML, and CSS remain in
1941
+ * the reviewed presentation/authority contract and cannot be authored here.
1942
+ */
1943
+ declare function applyMembershipTierMarkdown(presentation: MembershipTierPresentation, source: string): MembershipTierMarkdownResult;
1944
+ /** Apply constrained membership Markdown or fail closed with actionable errors. */
1945
+ declare function membershipTierPresentationFromMarkdown(presentation: MembershipTierPresentation, source: string): MembershipTierPresentation;
1946
+
1947
+ export { type AccountModel, type AdminNotificationTrigger, type Applicant, type ApplicationBookingPatch, type ApplicationRecord, type ApplicationSummary, type Attr, type AttrType, type Chapter, type ChapterApplication, type ChapterAuth, type ChapterBrand, type ChapterConfig, type ChapterCopy, type ChapterCopyInput, type ChapterDb, type ChapterEmails, type ChapterIntegrationDescriptor, type ChapterIntegrationOptions, type ChapterMode, type ChapterNetwork, type ChapterNetworkReader, type ChapterNetworkTarget, type ChapterOperations, type ChapterPipeline, type ChapterPolicy, type ChapterPrices, type ChapterRunbookHints, type ChapterScheduling, type ChapterSends, type ChapterTier, type ChapterTierConfig, type ClerkInviteInput, type ClerkMetadataInput, type ClerkResult, type ClerkUserInput, type ClerkUserRecord, type CompiledChapterBrandTokens, DEFAULT_CHAPTER_COPY, DEFAULT_SHARE_FIELDS, type DashboardMetricData, type DashboardMetricSeries, type DbOp, type DbRules, type DbSchema, type DeliveryDecision, type EmailGroup, type EmailTemplate, type EmailTemplateRow, type Entity, type ExistingMeeting, type GuardResult, type IntegrationDescriptor, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type IntegrationSync, type JoinConfigGroup, type JoinConfigTier, type LeaderCrmOptions, type LeaderFormationConfig, type LiveEvent, MEMBERSHIP_PAGE_RENDERER, type MailSender, type MeetingForReconcile, type MeetingRecord, type MeetingReschedulePatch, type MemberApplication, type MemberSession, type MembershipPageDocument, type MembershipPageValidationOptions, type MembershipPageValidationResult, type MembershipTierAuthority, type MembershipTierCallout, type MembershipTierCapacity, type MembershipTierMarkdownResult, type MembershipTierPresentation, type MembershipTierVariant, type NetworkRecord, type NetworkRecordNote, type NetworkRecordPage, type NetworkRollup, type NetworkRollupTarget, type NetworkSharedNote, type NetworkSnapshot, type NewMeetingRow, type NotifyDeps, type NotifyInput, type NotifyResult, type PaymentsGroup, type ProjectionDeps, type ReconcileDecision, type ResolvedApplication, type ResolvedAuth, type ResolvedLeaderFormation, type ResolvedNetwork, type ResolvedNetworkReader, type ResolvedNetworkTarget, type ResolvedOperations, type ResolvedPipeline, type ResolvedScheduling, type ResolvedSends, type RoleChangeContext, type Rule, SCHEDULING_DEFAULTS, type SchedulingErrors, type SecretMode, type SecretStore, type SessionUser, type SharedBusiness, type SharedPerson, type SharedRecord, type SharedRecordV1, type SharedRecordV2, type StripeEvent, type StripeResult, type SubmitResult, type TierGroup, type TierGroupRow, type WebhookEvent, applicantProfile, applicationBookingUpdate, applicationSummary, applyMembershipTierMarkdown, backfillCrm, bookingDecision, brandTokens, bucketSeries, buildGroupSeed, buildTierSeeds, canApprove, canBook, canChangeRole, canTransition, canceledPatch, chapterBrandFromTokens, chapterDb, clampArray, clerkGetUser, clerkGetUserByEmail, clerkIntegration, clerkInviteRequest, clerkListUsers, clerkSetRole, clerkUserRequest, createChapterIntegration, createClerkInvitation, createClerkUser, dashboardMetricData, defaultCrm, defineChapter, emailGroupFrom, endForSlot, findApplicationRef, findTier, firstPaymentPatch, formatChapterCopy, formationFields, getVaultSecret, hasDisclaimerAck, introIdempotencyKey, isAdminRole, isAlreadySent, isReconcilable, isSlotAvailable, isValidEmail, joinConfig, joinConfigTiers, leaderCrmConfig, loadOfferableTiers, loadTiers, meetingCreateRow, meetingRescheduleUpdate, memberApplication, memberSession, membershipPageDocument, membershipTierPresentationFromMarkdown, networkSourceTag, normalizeSharedRecord, normalizeWebhookEvent, offerableTiers, paymentsReady, personInputFromApp, planDelivery, projectApplicant, projectSharedRecord, reconcileMeetings, refundedPatch, render, renderSummary, renderTemplateBody, renewalPatch, resolveApplication, resolveAuth, resolveChapterCopy, resolveLeaderFormation, resolvePipeline, resolveScheduling, resolveTiers, roleFromClaim, sendTemplated, sharedPersonInput, sharedRecordFromCrm, slotWindow, stageIndex, stripeCall, subAnnualCents, submitApplication, subscriptionIdempotencyKey, syncApplicationToCrm, tierIsFree, tierPayable, updateClerkUserMetadata, updateClerkUserMetadataByEmail, validateMembershipPageDocument, validateScheduling, webhookMutationId };
package/dist/index.d.ts CHANGED
@@ -1921,4 +1921,27 @@ declare function validateMembershipPageDocument(input: unknown, options?: Member
1921
1921
  /** Validate a document or fail closed with all actionable validation errors. */
1922
1922
  declare function membershipPageDocument(input: unknown, options?: MembershipPageValidationOptions): MembershipPageDocument;
1923
1923
 
1924
- export { type AccountModel, type AdminNotificationTrigger, type Applicant, type ApplicationBookingPatch, type ApplicationRecord, type ApplicationSummary, type Attr, type AttrType, type Chapter, type ChapterApplication, type ChapterAuth, type ChapterBrand, type ChapterConfig, type ChapterCopy, type ChapterCopyInput, type ChapterDb, type ChapterEmails, type ChapterIntegrationDescriptor, type ChapterIntegrationOptions, type ChapterMode, type ChapterNetwork, type ChapterNetworkReader, type ChapterNetworkTarget, type ChapterOperations, type ChapterPipeline, type ChapterPolicy, type ChapterPrices, type ChapterRunbookHints, type ChapterScheduling, type ChapterSends, type ChapterTier, type ChapterTierConfig, type ClerkInviteInput, type ClerkMetadataInput, type ClerkResult, type ClerkUserInput, type ClerkUserRecord, type CompiledChapterBrandTokens, DEFAULT_CHAPTER_COPY, DEFAULT_SHARE_FIELDS, type DashboardMetricData, type DashboardMetricSeries, type DbOp, type DbRules, type DbSchema, type DeliveryDecision, type EmailGroup, type EmailTemplate, type EmailTemplateRow, type Entity, type ExistingMeeting, type GuardResult, type IntegrationDescriptor, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type IntegrationSync, type JoinConfigGroup, type JoinConfigTier, type LeaderCrmOptions, type LeaderFormationConfig, type LiveEvent, MEMBERSHIP_PAGE_RENDERER, type MailSender, type MeetingForReconcile, type MeetingRecord, type MeetingReschedulePatch, type MemberApplication, type MemberSession, type MembershipPageDocument, type MembershipPageValidationOptions, type MembershipPageValidationResult, type MembershipTierAuthority, type MembershipTierCallout, type MembershipTierCapacity, type MembershipTierPresentation, type MembershipTierVariant, type NetworkRecord, type NetworkRecordNote, type NetworkRecordPage, type NetworkRollup, type NetworkRollupTarget, type NetworkSharedNote, type NetworkSnapshot, type NewMeetingRow, type NotifyDeps, type NotifyInput, type NotifyResult, type PaymentsGroup, type ProjectionDeps, type ReconcileDecision, type ResolvedApplication, type ResolvedAuth, type ResolvedLeaderFormation, type ResolvedNetwork, type ResolvedNetworkReader, type ResolvedNetworkTarget, type ResolvedOperations, type ResolvedPipeline, type ResolvedScheduling, type ResolvedSends, type RoleChangeContext, type Rule, SCHEDULING_DEFAULTS, type SchedulingErrors, type SecretMode, type SecretStore, type SessionUser, type SharedBusiness, type SharedPerson, type SharedRecord, type SharedRecordV1, type SharedRecordV2, type StripeEvent, type StripeResult, type SubmitResult, type TierGroup, type TierGroupRow, type WebhookEvent, applicantProfile, applicationBookingUpdate, applicationSummary, backfillCrm, bookingDecision, brandTokens, bucketSeries, buildGroupSeed, buildTierSeeds, canApprove, canBook, canChangeRole, canTransition, canceledPatch, chapterBrandFromTokens, chapterDb, clampArray, clerkGetUser, clerkGetUserByEmail, clerkIntegration, clerkInviteRequest, clerkListUsers, clerkSetRole, clerkUserRequest, createChapterIntegration, createClerkInvitation, createClerkUser, dashboardMetricData, defaultCrm, defineChapter, emailGroupFrom, endForSlot, findApplicationRef, findTier, firstPaymentPatch, formatChapterCopy, formationFields, getVaultSecret, hasDisclaimerAck, introIdempotencyKey, isAdminRole, isAlreadySent, isReconcilable, isSlotAvailable, isValidEmail, joinConfig, joinConfigTiers, leaderCrmConfig, loadOfferableTiers, loadTiers, meetingCreateRow, meetingRescheduleUpdate, memberApplication, memberSession, membershipPageDocument, networkSourceTag, normalizeSharedRecord, normalizeWebhookEvent, offerableTiers, paymentsReady, personInputFromApp, planDelivery, projectApplicant, projectSharedRecord, reconcileMeetings, refundedPatch, render, renderSummary, renderTemplateBody, renewalPatch, resolveApplication, resolveAuth, resolveChapterCopy, resolveLeaderFormation, resolvePipeline, resolveScheduling, resolveTiers, roleFromClaim, sendTemplated, sharedPersonInput, sharedRecordFromCrm, slotWindow, stageIndex, stripeCall, subAnnualCents, submitApplication, subscriptionIdempotencyKey, syncApplicationToCrm, tierIsFree, tierPayable, updateClerkUserMetadata, updateClerkUserMetadataByEmail, validateMembershipPageDocument, validateScheduling, webhookMutationId };
1924
+ /** A presentation overlay parsed from the constrained membership Markdown convention. */
1925
+ type MembershipTierMarkdownResult = {
1926
+ ok: true;
1927
+ value: MembershipTierPresentation;
1928
+ } | {
1929
+ ok: false;
1930
+ errors: readonly string[];
1931
+ };
1932
+ /**
1933
+ * Apply authored Markdown to the text slots of an existing tier presentation.
1934
+ *
1935
+ * The convention is deliberately small and reviewable:
1936
+ * - prelude prose -> summary; prelude bullets -> benefits
1937
+ * - `## Summary`, `## Benefits`, `## Price note`, `## Callout: Label`,
1938
+ * and `## Action` target those exact renderer slots
1939
+ *
1940
+ * Identity, price, scarcity, variants, badges, links, HTML, and CSS remain in
1941
+ * the reviewed presentation/authority contract and cannot be authored here.
1942
+ */
1943
+ declare function applyMembershipTierMarkdown(presentation: MembershipTierPresentation, source: string): MembershipTierMarkdownResult;
1944
+ /** Apply constrained membership Markdown or fail closed with actionable errors. */
1945
+ declare function membershipTierPresentationFromMarkdown(presentation: MembershipTierPresentation, source: string): MembershipTierPresentation;
1946
+
1947
+ export { type AccountModel, type AdminNotificationTrigger, type Applicant, type ApplicationBookingPatch, type ApplicationRecord, type ApplicationSummary, type Attr, type AttrType, type Chapter, type ChapterApplication, type ChapterAuth, type ChapterBrand, type ChapterConfig, type ChapterCopy, type ChapterCopyInput, type ChapterDb, type ChapterEmails, type ChapterIntegrationDescriptor, type ChapterIntegrationOptions, type ChapterMode, type ChapterNetwork, type ChapterNetworkReader, type ChapterNetworkTarget, type ChapterOperations, type ChapterPipeline, type ChapterPolicy, type ChapterPrices, type ChapterRunbookHints, type ChapterScheduling, type ChapterSends, type ChapterTier, type ChapterTierConfig, type ClerkInviteInput, type ClerkMetadataInput, type ClerkResult, type ClerkUserInput, type ClerkUserRecord, type CompiledChapterBrandTokens, DEFAULT_CHAPTER_COPY, DEFAULT_SHARE_FIELDS, type DashboardMetricData, type DashboardMetricSeries, type DbOp, type DbRules, type DbSchema, type DeliveryDecision, type EmailGroup, type EmailTemplate, type EmailTemplateRow, type Entity, type ExistingMeeting, type GuardResult, type IntegrationDescriptor, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type IntegrationSync, type JoinConfigGroup, type JoinConfigTier, type LeaderCrmOptions, type LeaderFormationConfig, type LiveEvent, MEMBERSHIP_PAGE_RENDERER, type MailSender, type MeetingForReconcile, type MeetingRecord, type MeetingReschedulePatch, type MemberApplication, type MemberSession, type MembershipPageDocument, type MembershipPageValidationOptions, type MembershipPageValidationResult, type MembershipTierAuthority, type MembershipTierCallout, type MembershipTierCapacity, type MembershipTierMarkdownResult, type MembershipTierPresentation, type MembershipTierVariant, type NetworkRecord, type NetworkRecordNote, type NetworkRecordPage, type NetworkRollup, type NetworkRollupTarget, type NetworkSharedNote, type NetworkSnapshot, type NewMeetingRow, type NotifyDeps, type NotifyInput, type NotifyResult, type PaymentsGroup, type ProjectionDeps, type ReconcileDecision, type ResolvedApplication, type ResolvedAuth, type ResolvedLeaderFormation, type ResolvedNetwork, type ResolvedNetworkReader, type ResolvedNetworkTarget, type ResolvedOperations, type ResolvedPipeline, type ResolvedScheduling, type ResolvedSends, type RoleChangeContext, type Rule, SCHEDULING_DEFAULTS, type SchedulingErrors, type SecretMode, type SecretStore, type SessionUser, type SharedBusiness, type SharedPerson, type SharedRecord, type SharedRecordV1, type SharedRecordV2, type StripeEvent, type StripeResult, type SubmitResult, type TierGroup, type TierGroupRow, type WebhookEvent, applicantProfile, applicationBookingUpdate, applicationSummary, applyMembershipTierMarkdown, backfillCrm, bookingDecision, brandTokens, bucketSeries, buildGroupSeed, buildTierSeeds, canApprove, canBook, canChangeRole, canTransition, canceledPatch, chapterBrandFromTokens, chapterDb, clampArray, clerkGetUser, clerkGetUserByEmail, clerkIntegration, clerkInviteRequest, clerkListUsers, clerkSetRole, clerkUserRequest, createChapterIntegration, createClerkInvitation, createClerkUser, dashboardMetricData, defaultCrm, defineChapter, emailGroupFrom, endForSlot, findApplicationRef, findTier, firstPaymentPatch, formatChapterCopy, formationFields, getVaultSecret, hasDisclaimerAck, introIdempotencyKey, isAdminRole, isAlreadySent, isReconcilable, isSlotAvailable, isValidEmail, joinConfig, joinConfigTiers, leaderCrmConfig, loadOfferableTiers, loadTiers, meetingCreateRow, meetingRescheduleUpdate, memberApplication, memberSession, membershipPageDocument, membershipTierPresentationFromMarkdown, networkSourceTag, normalizeSharedRecord, normalizeWebhookEvent, offerableTiers, paymentsReady, personInputFromApp, planDelivery, projectApplicant, projectSharedRecord, reconcileMeetings, refundedPatch, render, renderSummary, renderTemplateBody, renewalPatch, resolveApplication, resolveAuth, resolveChapterCopy, resolveLeaderFormation, resolvePipeline, resolveScheduling, resolveTiers, roleFromClaim, sendTemplated, sharedPersonInput, sharedRecordFromCrm, slotWindow, stageIndex, stripeCall, subAnnualCents, submitApplication, subscriptionIdempotencyKey, syncApplicationToCrm, tierIsFree, tierPayable, updateClerkUserMetadata, updateClerkUserMetadataByEmail, validateMembershipPageDocument, validateScheduling, webhookMutationId };
package/dist/index.js CHANGED
@@ -2695,6 +2695,126 @@ function membershipPageDocument(input, options = {}) {
2695
2695
  if (!result.ok) throw new TypeError(`Invalid membership page document: ${result.errors.join("; ")}`);
2696
2696
  return result.value;
2697
2697
  }
2698
+
2699
+ // src/membership-markdown.ts
2700
+ var MAX_BENEFITS2 = 24;
2701
+ var MAX_MARKDOWN2 = 65536;
2702
+ var MAX_LABEL2 = 160;
2703
+ var MARKDOWN_SECTION = /^##\s+(.+?)\s*$/;
2704
+ var MARKDOWN_HEADING = /^#{1,6}\s+/;
2705
+ var MARKDOWN_BENEFIT = /^\s*[-*+]\s+(.+?)\s*$/;
2706
+ function markdownSection(rawHeading) {
2707
+ const heading = rawHeading.trim();
2708
+ const normalized = heading.toLowerCase();
2709
+ if (normalized === "summary") return { section: "summary" };
2710
+ if (normalized === "benefits") return { section: "benefits" };
2711
+ if (normalized === "price note" || normalized === "rate note") return { section: "priceNote" };
2712
+ if (normalized === "action" || normalized === "call to action") return { section: "action" };
2713
+ const callout = heading.match(/^callout(?:\s*[:—-]\s*(.+))?$/i);
2714
+ if (callout) return { section: "callout", ...callout[1]?.trim() ? { calloutLabel: callout[1].trim() } : {} };
2715
+ return {};
2716
+ }
2717
+ function markdownBenefits(lines, path, errors) {
2718
+ const benefits = [];
2719
+ for (const [index, line] of lines.entries()) {
2720
+ if (!line.trim()) continue;
2721
+ const match = line.match(MARKDOWN_BENEFIT);
2722
+ if (!match) {
2723
+ errors.push(`${path} line ${index + 1} must be a Markdown bullet`);
2724
+ continue;
2725
+ }
2726
+ const text = (match[1] ?? "").trim();
2727
+ if (text.length > 2e3) errors.push(`${path} line ${index + 1} must be at most 2,000 characters`);
2728
+ if (text) benefits.push(text);
2729
+ }
2730
+ if (benefits.length > MAX_BENEFITS2) errors.push(`${path} supports at most ${MAX_BENEFITS2} entries`);
2731
+ return benefits.slice(0, MAX_BENEFITS2);
2732
+ }
2733
+ function applyMembershipTierMarkdown(presentation, source) {
2734
+ if (typeof source !== "string") return { ok: false, errors: ["membership Markdown must be a string"] };
2735
+ if (source.length > MAX_MARKDOWN2) {
2736
+ return { ok: false, errors: [`membership Markdown must be at most ${MAX_MARKDOWN2.toLocaleString("en-US")} characters`] };
2737
+ }
2738
+ if (!source.trim()) return { ok: true, value: { ...presentation } };
2739
+ const errors = [];
2740
+ const sections = /* @__PURE__ */ new Map();
2741
+ const prelude = [];
2742
+ let current = null;
2743
+ for (const [index, line] of source.replace(/\r\n?/g, "\n").split("\n").entries()) {
2744
+ const heading = line.match(MARKDOWN_SECTION);
2745
+ if (heading) {
2746
+ const headingText = heading[1] ?? "";
2747
+ const parsed = markdownSection(headingText);
2748
+ if (!parsed.section) {
2749
+ errors.push(`membership Markdown heading "${headingText.trim()}" is not supported`);
2750
+ current = null;
2751
+ continue;
2752
+ }
2753
+ if (sections.has(parsed.section)) {
2754
+ errors.push(`membership Markdown repeats the ${parsed.section} section`);
2755
+ current = parsed.section;
2756
+ continue;
2757
+ }
2758
+ sections.set(parsed.section, { lines: [], ...parsed.calloutLabel ? { calloutLabel: parsed.calloutLabel } : {} });
2759
+ current = parsed.section;
2760
+ continue;
2761
+ }
2762
+ if (MARKDOWN_HEADING.test(line)) {
2763
+ errors.push(`membership Markdown line ${index + 1} uses an unsupported heading`);
2764
+ continue;
2765
+ }
2766
+ if (current) sections.get(current)?.lines.push(line);
2767
+ else prelude.push(line);
2768
+ }
2769
+ const preludeBenefits = [];
2770
+ const preludeSummary = [];
2771
+ for (const line of prelude) {
2772
+ const benefit = line.match(MARKDOWN_BENEFIT);
2773
+ if (benefit) preludeBenefits.push((benefit[1] ?? "").trim());
2774
+ else preludeSummary.push(line);
2775
+ }
2776
+ if (preludeBenefits.length > MAX_BENEFITS2) errors.push(`membership Markdown prelude supports at most ${MAX_BENEFITS2} benefits`);
2777
+ if (preludeBenefits.some((benefit) => benefit.length > 2e3)) errors.push("membership Markdown benefits must be at most 2,000 characters");
2778
+ const summarySection = sections.get("summary");
2779
+ const benefitsSection = sections.get("benefits");
2780
+ const priceNoteSection = sections.get("priceNote");
2781
+ const calloutSection = sections.get("callout");
2782
+ const actionSection = sections.get("action");
2783
+ const summaryMarkdown = (summarySection?.lines ?? preludeSummary).join("\n").trim();
2784
+ const benefits = benefitsSection ? markdownBenefits(benefitsSection.lines, "membership Markdown Benefits", errors) : preludeBenefits.filter(Boolean).slice(0, MAX_BENEFITS2);
2785
+ const priceNoteMarkdown = priceNoteSection?.lines.join("\n").trim();
2786
+ const calloutBody = calloutSection?.lines.join("\n").trim();
2787
+ const actionLines = actionSection?.lines.filter((line) => line.trim());
2788
+ const ctaLabel = actionLines?.join(" ").trim();
2789
+ if (actionLines && actionLines.length !== 1) errors.push("membership Markdown Action must contain exactly one line");
2790
+ if (ctaLabel && ctaLabel.length > MAX_LABEL2) errors.push(`membership Markdown Action must be at most ${MAX_LABEL2} characters`);
2791
+ if (calloutSection && !calloutBody) errors.push("membership Markdown Callout must include body copy");
2792
+ if (calloutSection?.calloutLabel && calloutSection.calloutLabel.length > MAX_LABEL2) {
2793
+ errors.push(`membership Markdown Callout label must be at most ${MAX_LABEL2} characters`);
2794
+ }
2795
+ if (errors.length) return { ok: false, errors };
2796
+ return {
2797
+ ok: true,
2798
+ value: {
2799
+ ...presentation,
2800
+ ...summaryMarkdown ? { summaryMarkdown } : {},
2801
+ ...benefitsSection || preludeBenefits.length ? { benefits } : {},
2802
+ ...priceNoteSection ? { priceNoteMarkdown: priceNoteMarkdown ?? "" } : {},
2803
+ ...calloutSection ? {
2804
+ callout: {
2805
+ ...calloutSection.calloutLabel || presentation.callout?.label ? { label: calloutSection.calloutLabel ?? presentation.callout?.label } : {},
2806
+ bodyMarkdown: calloutBody ?? ""
2807
+ }
2808
+ } : {},
2809
+ ...actionSection && ctaLabel ? { ctaLabel } : {}
2810
+ }
2811
+ };
2812
+ }
2813
+ function membershipTierPresentationFromMarkdown(presentation, source) {
2814
+ const result = applyMembershipTierMarkdown(presentation, source);
2815
+ if (!result.ok) throw new TypeError(`Invalid membership Markdown: ${result.errors.join("; ")}`);
2816
+ return result.value;
2817
+ }
2698
2818
  export {
2699
2819
  DEFAULT_CHAPTER_COPY,
2700
2820
  DEFAULT_SHARE_FIELDS,
@@ -2703,6 +2823,7 @@ export {
2703
2823
  applicantProfile,
2704
2824
  applicationBookingUpdate,
2705
2825
  applicationSummary,
2826
+ applyMembershipTierMarkdown,
2706
2827
  backfillCrm,
2707
2828
  bookingDecision,
2708
2829
  brandTokens,
@@ -2755,6 +2876,7 @@ export {
2755
2876
  memberApplication,
2756
2877
  memberSession,
2757
2878
  membershipPageDocument,
2879
+ membershipTierPresentationFromMarkdown,
2758
2880
  networkSourceTag,
2759
2881
  normalizeSharedRecord,
2760
2882
  normalizeWebhookEvent,