@claritylabs/cl-sdk 3.0.23 → 3.0.24

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.mjs CHANGED
@@ -2944,6 +2944,9 @@ function cleanValue(value) {
2944
2944
  if (!value) return void 0;
2945
2945
  return normalizeWhitespace3(value.replace(/^[\s:;#-]+|[\s;,.]+$/g, ""));
2946
2946
  }
2947
+ function cleanCoverageLabel(value) {
2948
+ return cleanValue(value)?.replace(/^column\s+\d+\s*:\s*/i, "");
2949
+ }
2947
2950
  function moneyValue(value) {
2948
2951
  const clean = cleanValue(value);
2949
2952
  if (!clean) return void 0;
@@ -3001,12 +3004,12 @@ function inferDocumentType(nodes) {
3001
3004
  }
3002
3005
  function coverageNameFromRow(text) {
3003
3006
  const labelled = text.match(/\b(?:coverage|coverage part|line)\s*:?\s*([^|;$]{3,80})/i)?.[1];
3004
- if (labelled) return cleanValue(labelled);
3005
- const parts = text.split(/\s+\|\s+| {2,}|\t/).map(cleanValue).filter(Boolean);
3007
+ if (labelled) return cleanCoverageLabel(labelled);
3008
+ const parts = text.split(/\s+\|\s+| {2,}|\t/).map(cleanCoverageLabel).filter(Boolean);
3006
3009
  const first = parts.find(
3007
3010
  (part) => !/^(limit|limits?|deductible|premium|amount|basis|rate|retroactive|aggregate|each occurrence)$/i.test(part) && !/^\$?[\d,]+/.test(part)
3008
3011
  );
3009
- return cleanValue(first);
3012
+ return cleanCoverageLabel(first);
3010
3013
  }
3011
3014
  function limitFromText(text) {
3012
3015
  return moneyValue(
@@ -3123,21 +3126,40 @@ function endorsementAncestor(node, byId) {
3123
3126
  function endorsementNumberFrom(value) {
3124
3127
  return cleanValue(value?.match(/\bendorsement\s+no\.?\s*([0-9A-Z-]+)/i)?.[1]);
3125
3128
  }
3129
+ function endorsementNameFrom(node) {
3130
+ const candidates = [node.title, node.textExcerpt, node.description, nodeText(node)].filter(Boolean);
3131
+ for (const candidate of candidates) {
3132
+ const match = candidate.match(/\bendorsement\s+no\.?\s*([0-9A-Z-]+)\s*[—-]\s*(.{3,140}?)(?=\s+This\s+endorsement\b|\.|$)/i);
3133
+ if (match) return cleanValue(`Endorsement No. ${match[1]} - ${match[2]}`) ?? node.title;
3134
+ }
3135
+ return node.title;
3136
+ }
3126
3137
  function sourceIds(nodes) {
3127
3138
  return {
3128
3139
  sourceNodeIds: [...new Set(nodes.map((node) => node.id))],
3129
3140
  sourceSpanIds: [...new Set(nodes.flatMap((node) => node.sourceSpanIds))]
3130
3141
  };
3131
3142
  }
3143
+ function relabelGenericTerm(term, label) {
3144
+ const cleanLabel = cleanValue(label);
3145
+ if (!cleanLabel || !/^column\s+\d+$/i.test(term.label)) return term;
3146
+ return {
3147
+ ...term,
3148
+ kind: termKind(cleanLabel, term.value),
3149
+ label: cleanLabel
3150
+ };
3151
+ }
3132
3152
  function termFromCell(params) {
3133
3153
  const value = cleanValue(params.value);
3134
3154
  if (!value) return void 0;
3135
3155
  const nodes = [params.row, params.cell].filter((node) => Boolean(node));
3156
+ const kind = termKind(params.label, value);
3157
+ const amount = moneyAmount(value);
3136
3158
  return {
3137
- kind: termKind(params.label, value),
3159
+ kind,
3138
3160
  label: params.label,
3139
3161
  value,
3140
- ...moneyAmount(value) !== void 0 ? { amount: moneyAmount(value) } : {},
3162
+ ...amount !== void 0 && kind !== "retroactive_date" ? { amount } : {},
3141
3163
  ...params.appliesTo ? { appliesTo: params.appliesTo } : {},
3142
3164
  ...sourceIds(nodes)
3143
3165
  };
@@ -3174,7 +3196,7 @@ function nameFromRow(row, children) {
3174
3196
  const cells = cellRows(row, children);
3175
3197
  const named = cells.find((cell) => isNameCell(cell.label, cell.value));
3176
3198
  if (named) return cleanValue(named.value);
3177
- return coverageNameFromRow(nodeText(row));
3199
+ return coverageNameFromRow(row.textExcerpt ?? row.description ?? nodeText(row));
3178
3200
  }
3179
3201
  function legacyLimit(terms) {
3180
3202
  return terms.find(
@@ -3227,31 +3249,39 @@ function coverageFromEndorsement(endorsement, children) {
3227
3249
  const terms = uniqueTerms(rows.flatMap(
3228
3250
  (row) => termsFromRow(row, children).map((term) => {
3229
3251
  const appliesTo = nameFromRow(row, children);
3230
- return appliesTo && !/^(each claim limit|aggregate limit|retroactive date)$/i.test(appliesTo) ? { ...term, appliesTo } : term;
3252
+ const labelled = relabelGenericTerm(term, appliesTo);
3253
+ return appliesTo && labelled.label !== appliesTo ? { ...labelled, appliesTo } : labelled;
3231
3254
  })
3232
3255
  ));
3233
3256
  if (terms.length === 0) return void 0;
3234
3257
  const ids = sourceIds([endorsement, ...rows, ...rows.flatMap((row) => directChildren(row, children))]);
3258
+ const name = endorsementNameFrom(endorsement);
3235
3259
  return {
3236
- name: endorsement.title,
3260
+ name,
3237
3261
  limit: legacyLimit(terms),
3238
3262
  deductible: legacyDeductible(terms),
3239
3263
  premium: legacyPremium(terms),
3240
3264
  retroactiveDate: retroDate(terms),
3241
3265
  formNumber: typeof endorsement.metadata?.formNumber === "string" ? endorsement.metadata.formNumber : void 0,
3242
- sectionRef: endorsement.title,
3266
+ sectionRef: name,
3243
3267
  coverageOrigin: "endorsement",
3244
- endorsementNumber: endorsementNumberFrom(endorsement.title),
3268
+ endorsementNumber: endorsementNumberFrom(name),
3245
3269
  limits: terms,
3246
3270
  ...ids
3247
3271
  };
3248
3272
  }
3273
+ function hasDescendantEndorsementWithTableRows(endorsement, children) {
3274
+ return descendants(endorsement, children).some(
3275
+ (node) => node.kind === "endorsement" && descendants(node, children).some((descendant) => descendant.kind === "table_row")
3276
+ );
3277
+ }
3249
3278
  function buildCoverages(nodes) {
3250
3279
  const children = childMap(nodes);
3251
3280
  const byId = new Map(nodes.map((node) => [node.id, node]));
3252
3281
  const coverages = [];
3253
3282
  const seen = /* @__PURE__ */ new Set();
3254
3283
  for (const endorsement of nodes.filter((node) => node.kind === "endorsement")) {
3284
+ if (hasDescendantEndorsementWithTableRows(endorsement, children)) continue;
3255
3285
  const coverage = coverageFromEndorsement(endorsement, children);
3256
3286
  if (!coverage) continue;
3257
3287
  const key = [coverage.name.toLowerCase(), coverage.sourceNodeIds.join(",")].join("|");
@@ -3436,7 +3466,7 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
3436
3466
  sourceSpanIds
3437
3467
  };
3438
3468
  };
3439
- const coverages = Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) => {
3469
+ const coverages = base.coverages.length > 0 ? base.coverages : Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) => {
3440
3470
  const record = coverage;
3441
3471
  const limits = Array.isArray(record.limits) ? record.limits.filter(
3442
3472
  (term) => Boolean(term) && typeof term === "object" && !Array.isArray(term)