ChemPal Documentation - v1.6.0
    Preparing search index...
    • Parses Synthetika product text (an HTML shortDescription) into a PurchaseRestriction. The source formatting is inconsistent (double spaces, nbsp, emoji/mojibake, multiple <p>/<br> blocks), so all matching is case-insensitive over whitespace-normalized text. When a delivery restriction is detected but can't be resolved to a specific country or the EU, the product is flagged restrictedDelivery (excluded to be safe). Declaration-of-use text is captured but never excludes.

      Parameters

      • Optionalhtml: string

        The product's shortDescription HTML (or any value)

      Returns undefined | PurchaseRestriction

      The parsed restriction, or undefined when the text carries no restriction

      parseSynthetikaRestrictions("<p>We do not ship this product to: US, DE | Unless government approved</p>");
      // { excludedCountries: ["US", "DE"], note: "We do not ship this product to: US, DE | Unless government approved" }
      parseSynthetikaRestrictions("<p>ONLY COMPANY ORDERS</p>");
      // { buyerRestricted: true, note: "ONLY COMPANY ORDERS" }
      parseSynthetikaRestrictions("<p>High purity sodium chloride.</p>"); // undefined
      export function parseSynthetikaRestrictions(html?: string): PurchaseRestriction | undefined {
      if (typeof html !== 'string' || html.trim().length === 0) {
      return undefined;
      }
      const text = normalizeRestrictionText(htmlToAscii(html));
      if (text.length === 0) {
      return undefined;
      }

      const result: PurchaseRestriction = {};
      const excluded: CountryCode[] = [];

      // Region denylist: "We do not ship this product to: <comma list>". The capture stops at
      // a "|" (the "Unless government approved" caveat), a "<", or a line break.
      const denyMatch = text.match(/we do not ship this product to:\s*([^|<\n]+)/i);
      if (denyMatch) {
      for (const token of denyMatch[1].split(',')) {
      const code = resolveCountryToken(token);
      if (code !== undefined && !excluded.includes(code)) {
      excluded.push(code);
      }
      }
      }

      // Conditional region: "shipping to <country> possible only ...". Treat the named country
      // as excluded (the condition — ChemVerbots compliance, etc. — is unverifiable here).
      let conditionalResolved = false;
      const conditionalMatch = text.match(/shipping to ([a-z ]+?) possible only/i);
      if (conditionalMatch) {
      const code = resolveCountryToken(conditionalMatch[1]);
      if (code !== undefined) {
      if (!excluded.includes(code)) {
      excluded.push(code);
      }
      conditionalResolved = true;
      }
      }

      // EU-only allowlist.
      if (
      /possible only to selected eu countries/i.test(text) ||
      /not available for export outside the european union/i.test(text) ||
      /outside the eu\b/i.test(text)
      ) {
      result.euOnly = true;
      }

      // Catch-all: a "possible only to/if" delivery restriction we couldn't resolve to a
      // country or the EU. Exclude everyone to be safe.
      if (/possible only (to|if)/i.test(text) && !result.euOnly && !conditionalResolved) {
      result.restrictedDelivery = true;
      }

      if (BUYER_PATTERNS.some((pattern) => pattern.test(text))) {
      result.buyerRestricted = true;
      }

      if (
      /declaration of (intended )?use/i.test(text) ||
      /requires a written declaration/i.test(text)
      ) {
      result.declarationOfUseRequired = true;
      }

      if (excluded.length > 0) {
      result.excludedCountries = excluded;
      }

      if (Object.keys(result).length === 0) {
      return undefined;
      }
      result.note = text;
      return result;
      }