@odla-ai/chapter 0.32.1 → 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.cjs +122 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +122 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -27,6 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
applicantProfile: () => applicantProfile,
|
|
28
28
|
applicationBookingUpdate: () => applicationBookingUpdate,
|
|
29
29
|
applicationSummary: () => applicationSummary,
|
|
30
|
+
applyMembershipTierMarkdown: () => applyMembershipTierMarkdown,
|
|
30
31
|
backfillCrm: () => backfillCrm,
|
|
31
32
|
bookingDecision: () => bookingDecision,
|
|
32
33
|
brandTokens: () => brandTokens,
|
|
@@ -79,6 +80,7 @@ __export(index_exports, {
|
|
|
79
80
|
memberApplication: () => memberApplication,
|
|
80
81
|
memberSession: () => memberSession,
|
|
81
82
|
membershipPageDocument: () => membershipPageDocument,
|
|
83
|
+
membershipTierPresentationFromMarkdown: () => membershipTierPresentationFromMarkdown,
|
|
82
84
|
networkSourceTag: () => networkSourceTag,
|
|
83
85
|
normalizeSharedRecord: () => normalizeSharedRecord,
|
|
84
86
|
normalizeWebhookEvent: () => normalizeWebhookEvent,
|
|
@@ -2816,4 +2818,124 @@ function membershipPageDocument(input, options = {}) {
|
|
|
2816
2818
|
if (!result.ok) throw new TypeError(`Invalid membership page document: ${result.errors.join("; ")}`);
|
|
2817
2819
|
return result.value;
|
|
2818
2820
|
}
|
|
2821
|
+
|
|
2822
|
+
// src/membership-markdown.ts
|
|
2823
|
+
var MAX_BENEFITS2 = 24;
|
|
2824
|
+
var MAX_MARKDOWN2 = 65536;
|
|
2825
|
+
var MAX_LABEL2 = 160;
|
|
2826
|
+
var MARKDOWN_SECTION = /^##\s+(.+?)\s*$/;
|
|
2827
|
+
var MARKDOWN_HEADING = /^#{1,6}\s+/;
|
|
2828
|
+
var MARKDOWN_BENEFIT = /^\s*[-*+]\s+(.+?)\s*$/;
|
|
2829
|
+
function markdownSection(rawHeading) {
|
|
2830
|
+
const heading = rawHeading.trim();
|
|
2831
|
+
const normalized = heading.toLowerCase();
|
|
2832
|
+
if (normalized === "summary") return { section: "summary" };
|
|
2833
|
+
if (normalized === "benefits") return { section: "benefits" };
|
|
2834
|
+
if (normalized === "price note" || normalized === "rate note") return { section: "priceNote" };
|
|
2835
|
+
if (normalized === "action" || normalized === "call to action") return { section: "action" };
|
|
2836
|
+
const callout = heading.match(/^callout(?:\s*[:—-]\s*(.+))?$/i);
|
|
2837
|
+
if (callout) return { section: "callout", ...callout[1]?.trim() ? { calloutLabel: callout[1].trim() } : {} };
|
|
2838
|
+
return {};
|
|
2839
|
+
}
|
|
2840
|
+
function markdownBenefits(lines, path, errors) {
|
|
2841
|
+
const benefits = [];
|
|
2842
|
+
for (const [index, line] of lines.entries()) {
|
|
2843
|
+
if (!line.trim()) continue;
|
|
2844
|
+
const match = line.match(MARKDOWN_BENEFIT);
|
|
2845
|
+
if (!match) {
|
|
2846
|
+
errors.push(`${path} line ${index + 1} must be a Markdown bullet`);
|
|
2847
|
+
continue;
|
|
2848
|
+
}
|
|
2849
|
+
const text = (match[1] ?? "").trim();
|
|
2850
|
+
if (text.length > 2e3) errors.push(`${path} line ${index + 1} must be at most 2,000 characters`);
|
|
2851
|
+
if (text) benefits.push(text);
|
|
2852
|
+
}
|
|
2853
|
+
if (benefits.length > MAX_BENEFITS2) errors.push(`${path} supports at most ${MAX_BENEFITS2} entries`);
|
|
2854
|
+
return benefits.slice(0, MAX_BENEFITS2);
|
|
2855
|
+
}
|
|
2856
|
+
function applyMembershipTierMarkdown(presentation, source) {
|
|
2857
|
+
if (typeof source !== "string") return { ok: false, errors: ["membership Markdown must be a string"] };
|
|
2858
|
+
if (source.length > MAX_MARKDOWN2) {
|
|
2859
|
+
return { ok: false, errors: [`membership Markdown must be at most ${MAX_MARKDOWN2.toLocaleString("en-US")} characters`] };
|
|
2860
|
+
}
|
|
2861
|
+
if (!source.trim()) return { ok: true, value: { ...presentation } };
|
|
2862
|
+
const errors = [];
|
|
2863
|
+
const sections = /* @__PURE__ */ new Map();
|
|
2864
|
+
const prelude = [];
|
|
2865
|
+
let current = null;
|
|
2866
|
+
for (const [index, line] of source.replace(/\r\n?/g, "\n").split("\n").entries()) {
|
|
2867
|
+
const heading = line.match(MARKDOWN_SECTION);
|
|
2868
|
+
if (heading) {
|
|
2869
|
+
const headingText = heading[1] ?? "";
|
|
2870
|
+
const parsed = markdownSection(headingText);
|
|
2871
|
+
if (!parsed.section) {
|
|
2872
|
+
errors.push(`membership Markdown heading "${headingText.trim()}" is not supported`);
|
|
2873
|
+
current = null;
|
|
2874
|
+
continue;
|
|
2875
|
+
}
|
|
2876
|
+
if (sections.has(parsed.section)) {
|
|
2877
|
+
errors.push(`membership Markdown repeats the ${parsed.section} section`);
|
|
2878
|
+
current = parsed.section;
|
|
2879
|
+
continue;
|
|
2880
|
+
}
|
|
2881
|
+
sections.set(parsed.section, { lines: [], ...parsed.calloutLabel ? { calloutLabel: parsed.calloutLabel } : {} });
|
|
2882
|
+
current = parsed.section;
|
|
2883
|
+
continue;
|
|
2884
|
+
}
|
|
2885
|
+
if (MARKDOWN_HEADING.test(line)) {
|
|
2886
|
+
errors.push(`membership Markdown line ${index + 1} uses an unsupported heading`);
|
|
2887
|
+
continue;
|
|
2888
|
+
}
|
|
2889
|
+
if (current) sections.get(current)?.lines.push(line);
|
|
2890
|
+
else prelude.push(line);
|
|
2891
|
+
}
|
|
2892
|
+
const preludeBenefits = [];
|
|
2893
|
+
const preludeSummary = [];
|
|
2894
|
+
for (const line of prelude) {
|
|
2895
|
+
const benefit = line.match(MARKDOWN_BENEFIT);
|
|
2896
|
+
if (benefit) preludeBenefits.push((benefit[1] ?? "").trim());
|
|
2897
|
+
else preludeSummary.push(line);
|
|
2898
|
+
}
|
|
2899
|
+
if (preludeBenefits.length > MAX_BENEFITS2) errors.push(`membership Markdown prelude supports at most ${MAX_BENEFITS2} benefits`);
|
|
2900
|
+
if (preludeBenefits.some((benefit) => benefit.length > 2e3)) errors.push("membership Markdown benefits must be at most 2,000 characters");
|
|
2901
|
+
const summarySection = sections.get("summary");
|
|
2902
|
+
const benefitsSection = sections.get("benefits");
|
|
2903
|
+
const priceNoteSection = sections.get("priceNote");
|
|
2904
|
+
const calloutSection = sections.get("callout");
|
|
2905
|
+
const actionSection = sections.get("action");
|
|
2906
|
+
const summaryMarkdown = (summarySection?.lines ?? preludeSummary).join("\n").trim();
|
|
2907
|
+
const benefits = benefitsSection ? markdownBenefits(benefitsSection.lines, "membership Markdown Benefits", errors) : preludeBenefits.filter(Boolean).slice(0, MAX_BENEFITS2);
|
|
2908
|
+
const priceNoteMarkdown = priceNoteSection?.lines.join("\n").trim();
|
|
2909
|
+
const calloutBody = calloutSection?.lines.join("\n").trim();
|
|
2910
|
+
const actionLines = actionSection?.lines.filter((line) => line.trim());
|
|
2911
|
+
const ctaLabel = actionLines?.join(" ").trim();
|
|
2912
|
+
if (actionLines && actionLines.length !== 1) errors.push("membership Markdown Action must contain exactly one line");
|
|
2913
|
+
if (ctaLabel && ctaLabel.length > MAX_LABEL2) errors.push(`membership Markdown Action must be at most ${MAX_LABEL2} characters`);
|
|
2914
|
+
if (calloutSection && !calloutBody) errors.push("membership Markdown Callout must include body copy");
|
|
2915
|
+
if (calloutSection?.calloutLabel && calloutSection.calloutLabel.length > MAX_LABEL2) {
|
|
2916
|
+
errors.push(`membership Markdown Callout label must be at most ${MAX_LABEL2} characters`);
|
|
2917
|
+
}
|
|
2918
|
+
if (errors.length) return { ok: false, errors };
|
|
2919
|
+
return {
|
|
2920
|
+
ok: true,
|
|
2921
|
+
value: {
|
|
2922
|
+
...presentation,
|
|
2923
|
+
...summaryMarkdown ? { summaryMarkdown } : {},
|
|
2924
|
+
...benefitsSection || preludeBenefits.length ? { benefits } : {},
|
|
2925
|
+
...priceNoteSection ? { priceNoteMarkdown: priceNoteMarkdown ?? "" } : {},
|
|
2926
|
+
...calloutSection ? {
|
|
2927
|
+
callout: {
|
|
2928
|
+
...calloutSection.calloutLabel || presentation.callout?.label ? { label: calloutSection.calloutLabel ?? presentation.callout?.label } : {},
|
|
2929
|
+
bodyMarkdown: calloutBody ?? ""
|
|
2930
|
+
}
|
|
2931
|
+
} : {},
|
|
2932
|
+
...actionSection && ctaLabel ? { ctaLabel } : {}
|
|
2933
|
+
}
|
|
2934
|
+
};
|
|
2935
|
+
}
|
|
2936
|
+
function membershipTierPresentationFromMarkdown(presentation, source) {
|
|
2937
|
+
const result = applyMembershipTierMarkdown(presentation, source);
|
|
2938
|
+
if (!result.ok) throw new TypeError(`Invalid membership Markdown: ${result.errors.join("; ")}`);
|
|
2939
|
+
return result.value;
|
|
2940
|
+
}
|
|
2819
2941
|
//# sourceMappingURL=index.cjs.map
|