{"version":3,"file":"text.mjs","sources":["../../../src/tools/text.ts"],"sourcesContent":["import type { DateTimeOptions } from 'luxon'\nimport { DateTime } from 'luxon'\nimport uuidv7 from './uuidv7'\nimport { Type } from './type'\n\nconst reEscape = /[&<>'\"]/g\nconst reUnescape = /&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34)/g\n\nconst escapeEntities: Record<string, string> = {\n  '&': '&amp',\n  '<': '&lt',\n  '>': '&gt',\n  '\\'': '&#39',\n  '\"': '&quot'\n}\n\nconst unescapeEntities: Record<string, string> = {\n  '&amp': '&',\n  '&#38': '&',\n  '&lt': '<',\n  '&#60': '<',\n  '&gt': '>',\n  '&#62': '>',\n  '&apos': '\\'',\n  '&#39': '\\'',\n  '&quot': '\"',\n  '&#34': '\"'\n}\n\n/**\n * A collection of text and date utilities used across the SDK.\n *\n * It groups together helpers for:\n * - generating identifiers (random strings, UUID v4 and UUID v7),\n * - encoding and decoding HTML entities,\n * - converting arbitrary values to numbers, integers, and booleans,\n * - changing the case and format of strings (camelCase, PascalCase, kebab-case),\n * - formatting numbers and dates,\n * - building `application/x-www-form-urlencoded` query strings.\n *\n * The class is exported as the `Text` singleton — you never instantiate it yourself.\n *\n * @example\n * ```ts\n * import { Text } from '@bitrix24/b24jssdk'\n *\n * Text.getUuidRfc4122()          // '019323ac-8ace-725b-a3dc-6a7c333da066'\n * Text.getDateForLog()           // '2026-05-04 09:53:51'\n * Text.numberFormat(1234.567, 2) // '1,234.57'\n * ```\n *\n * @see bitrix/js/main/core/src/lib/text.js\n */\nclass TextManager {\n  /**\n   * Generates a random `[a-z0-9]` string of the requested length.\n   *\n   * Each character is drawn from `Math.random()`, so the result is **not**\n   * cryptographically secure — use it for cache-busting keys and disposable\n   * ids, not for tokens or secrets.\n   *\n   * @param length - Number of characters to generate. Defaults to `8`.\n   * @returns A random lowercase alphanumeric string.\n   *\n   * @example\n   * ```ts\n   * Text.getRandom()   // 'a7f3k1z9'\n   * Text.getRandom(4)  // 'p2x8'\n   * ```\n   */\n  getRandom(length: number = 8): string {\n    return Array.from({ length })\n      .map(() => Math.trunc(Math.random() * 36).toString(36))\n      .join('')\n  }\n\n  /**\n   * Generates a locally-computed UUID v4 (random) string.\n   *\n   * The value is built from `Math.random()` and is **not**\n   * cryptographically secure. For a time-ordered, RFC 4122 identifier prefer\n   * {@link getUuidRfc4122}.\n   *\n   * @returns A UUID v4 formatted string (`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`).\n   *\n   * @example\n   * ```ts\n   * Text.getUniqId() // 'd2b8a1f0-3c4e-4a9b-8f7c-1e2d3a4b5c6d'\n   * ```\n   */\n  getUniqId(): string {\n    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n      const r = Math.trunc(Math.random() * 16)\n      const v = c === 'x' ? r : (r & 0x3) | 0x8\n      return v.toString(16)\n    })\n  }\n\n  /**\n   * Generates a time-ordered UUID v7 (RFC 4122).\n   *\n   * This is the identifier the SDK uses as the default request id, because its\n   * leading timestamp keeps generated ids sortable by creation time.\n   *\n   * @returns A UUID v7 formatted string.\n   *\n   * @example\n   * ```ts\n   * Text.getUuidRfc4122() // '019323ac-8ace-725b-a3dc-6a7c333da066'\n   * ```\n   */\n  getUuidRfc4122(): string {\n    return uuidv7()\n  }\n\n  /**\n   * Encodes the unsafe HTML characters `&`, `<`, `>`, `'`, and `\"` into their\n   * entity codes.\n   *\n   * To match the legacy Bitrix Framework behaviour the trailing `;` is\n   * deliberately omitted (`&amp` instead of `&amp;`). Non-string values are\n   * returned untouched.\n   *\n   * This is **not** a general-purpose HTML sanitizer: it only escapes those\n   * five characters and is not context-aware (it does not neutralise\n   * attribute-breakout, `javascript:` URLs, or markup outside the escaped set).\n   * Do not rely on it as the sole XSS defence for untrusted input rendered as\n   * HTML.\n   *\n   * @param value - The string to encode.\n   * @returns The encoded string, or the original value when it is not a string.\n   *\n   * @example\n   * ```ts\n   * Text.encode('<b>Tom & Jerry</b>') // '&ltb&gtTom &amp Jerry&lt/b&gt'\n   * ```\n   */\n  encode(value: string): string {\n    if (Type.isString(value)) {\n      return value.replace(reEscape, item => escapeEntities[item]!)\n    }\n\n    return value\n  }\n\n  /**\n   * Decodes HTML entities produced by {@link encode} back into their\n   * characters.\n   *\n   * Both the named entities (`&amp`, `&lt`, …) and their numeric equivalents\n   * (`&#38`, `&#60`, …) are recognised. Like {@link encode}, the tokens carry\n   * no trailing `;`, so a `;` that follows an entity in the input is left in\n   * place (`&amp;` decodes to `&;`). Non-string values are returned untouched.\n   *\n   * @param value - The string to decode.\n   * @returns The decoded string, or the original value when it is not a string.\n   *\n   * @example\n   * ```ts\n   * Text.decode('&ltb&gtTom &amp Jerry&lt/b&gt') // '<b>Tom & Jerry</b>'\n   * ```\n   */\n  decode(value: string): string {\n    if (Type.isString(value)) {\n      return value.replace(reUnescape, item => unescapeEntities[item]!)\n    }\n\n    return value\n  }\n\n  /**\n   * Parses a value into a floating-point number.\n   *\n   * Uses `Number.parseFloat`, so a leading numeric portion is accepted\n   * (`'12px'` → `12`). Any value that cannot be parsed becomes `0`.\n   *\n   * @param value - The value to convert.\n   * @returns The parsed number, or `0` when parsing fails.\n   *\n   * @example\n   * ```ts\n   * Text.toNumber('12.5') // 12.5\n   * Text.toNumber('abc')  // 0\n   * ```\n   */\n  toNumber(value: any): number {\n    const parsedValue = Number.parseFloat(value)\n\n    if (Type.isNumber(parsedValue)) {\n      return parsedValue\n    }\n\n    return 0.0\n  }\n\n  /**\n   * Parses a value into an integer (base 10).\n   *\n   * Any value that cannot be parsed becomes `0`.\n   *\n   * @param value - The value to convert.\n   * @returns The parsed integer, or `0` when parsing fails.\n   *\n   * @example\n   * ```ts\n   * Text.toInteger('42.9') // 42\n   * Text.toInteger('abc')  // 0\n   * ```\n   */\n  toInteger(value: any): number {\n    return this.toNumber(Number.parseInt(value, 10))\n  }\n\n  /**\n   * Interprets a value as a boolean.\n   *\n   * `true` is returned for `true`, `1`, `'true'`, `'y'`, and `'1'`\n   * (string comparison is case-insensitive). Extra truthy tokens can be added\n   * through `trueValues`; everything else yields `false`.\n   *\n   * @param value - The value to interpret.\n   * @param trueValues - Additional values that should be treated as `true`.\n   * @returns `true` when the value matches a truthy token, otherwise `false`.\n   *\n   * @example\n   * ```ts\n   * Text.toBoolean('Y')             // true\n   * Text.toBoolean('on', ['on'])    // true\n   * Text.toBoolean('no')            // false\n   * ```\n   */\n  toBoolean(value: any, trueValues: string[] = []): boolean {\n    const transformedValue = Type.isString(value) ? value.toLowerCase() : value\n    return ['true', 'y', '1', 1, true, ...trueValues].includes(transformedValue)\n  }\n\n  /**\n   * Converts a string to `camelCase`.\n   *\n   * Hyphens, underscores, and whitespace are treated as word separators. A\n   * fully uppercase string is lowercased (`'ABC'` → `'abc'`); an empty or\n   * non-filled string is returned untouched.\n   *\n   * @param str - The string to convert.\n   * @returns The `camelCase` string.\n   *\n   * @example\n   * ```ts\n   * Text.toCamelCase('get_user_id') // 'getUserId'\n   * Text.toCamelCase('Some Value')  // 'someValue'\n   * ```\n   */\n  toCamelCase(str: string): string {\n    if (!Type.isStringFilled(str)) {\n      return str\n    }\n\n    const separators = /[-_\\s]+(.)?/g\n    if (!separators.test(str)) {\n      return /^[A-Z]+$/.test(str)\n        ? str.toLowerCase()\n        : str[0]!.toLowerCase() + str.slice(1)\n    }\n\n    const camel = str\n      .toLowerCase()\n      .replace(separators, (_match, letter) =>\n        letter ? letter.toUpperCase() : ''\n      )\n\n    return camel[0]!.toLowerCase() + camel.slice(1)\n  }\n\n  /**\n   * Converts a string to `PascalCase`.\n   *\n   * Equivalent to `capitalize(toCamelCase(str))`. An empty or non-filled string\n   * is returned untouched.\n   *\n   * @param str - The string to convert.\n   * @returns The `PascalCase` string.\n   *\n   * @example\n   * ```ts\n   * Text.toPascalCase('get_user_id') // 'GetUserId'\n   * ```\n   */\n  toPascalCase(str: string): string {\n    if (!Type.isStringFilled(str)) {\n      return str\n    }\n\n    return this.capitalize(this.toCamelCase(str))\n  }\n\n  /**\n   * Converts a string to `kebab-case`.\n   *\n   * Splits on uppercase-letter boundaries as well as existing separators, so\n   * both `camelCase` and mixed-case acronyms are handled. An uppercase run that\n   * is immediately followed by a digit is split into single letters\n   * (`parseHTML5` → `parse-h-t-m-l-5`), because there is no word boundary\n   * between the acronym and the digit. An empty or non-filled string is\n   * returned untouched.\n   *\n   * @param str - The string to convert.\n   * @returns The `kebab-case` string.\n   *\n   * @example\n   * ```ts\n   * Text.toKebabCase('getUserId')      // 'get-user-id'\n   * Text.toKebabCase('XMLHttpRequest') // 'xml-http-request'\n   * ```\n   */\n  toKebabCase(str: string): string {\n    if (!Type.isStringFilled(str)) {\n      return str\n    }\n\n    const matches = str.match(\n      /[A-Z]{2,}(?=[A-Z][a-z]+\\d*|\\b)|[A-Z]?[a-z]+\\d*|[A-Z]|\\d+/g\n    )\n    if (!matches) {\n      return str\n    }\n\n    return matches.map(word => word.toLowerCase()).join('-')\n  }\n\n  /**\n   * Uppercases the first character of a string, leaving the rest untouched.\n   *\n   * An empty or non-filled string is returned untouched.\n   *\n   * @param str - The string to capitalize.\n   * @returns The capitalized string.\n   *\n   * @example\n   * ```ts\n   * Text.capitalize('hello') // 'Hello'\n   * ```\n   */\n  capitalize(str: string): string {\n    if (!Type.isStringFilled(str)) {\n      return str\n    }\n\n    return str[0]!.toUpperCase() + str.slice(1)\n  }\n\n  /**\n   * Formats a number with grouped thousands and a fixed number of decimals.\n   *\n   * Mirrors the algorithm Bitrix24 uses on the server: non-finite inputs are\n   * treated as `0`, the fractional part is rounded to `decimals` places, and\n   * the thousands separator is inserted every three digits left of the decimal\n   * point.\n   *\n   * @param number - The number to format.\n   * @param decimals - Number of digits after the decimal point. Defaults to `0`.\n   * @param decPoint - The decimal-point character. Defaults to `'.'`.\n   * @param thousandsSep - The thousands separator. Defaults to `','`.\n   * @returns The formatted number as a string.\n   *\n   * @example\n   * ```ts\n   * Text.numberFormat(1234.567, 2)              // '1,234.57'\n   * Text.numberFormat(1234.567, 2, ',', ' ')    // '1 234,57'\n   * ```\n   */\n  numberFormat(\n    number: number,\n    decimals: number = 0,\n    decPoint: string = '.',\n    thousandsSep: string = ','\n  ): string {\n    const value = Number.isFinite(number) ? number : 0\n    const fractionDigits = Number.isFinite(decimals) ? Math.abs(decimals) : 0\n\n    const roundTo = (n: number, digits: number): number => {\n      const factor = 10 ** digits\n      return Math.round(n * factor) / factor\n    }\n\n    const parts = (fractionDigits ? roundTo(value, fractionDigits) : Math.round(value))\n      .toString()\n      .split('.')\n\n    if (parts[0] && parts[0].length > 3) {\n      parts[0] = parts[0].replace(/\\B(?=(?:\\d{3})+(?!\\d))/g, thousandsSep)\n    }\n\n    if ((parts[1] || '').length < fractionDigits) {\n      parts[1] = (parts[1] || '').padEnd(fractionDigits, '0')\n    }\n\n    return parts.join(decPoint)\n  }\n\n  /**\n   * Converts a string into a Luxon `DateTime`.\n   *\n   * When `template` is provided the string is parsed with\n   * `DateTime.fromFormat`; otherwise it is parsed as ISO 8601 via\n   * `DateTime.fromISO`.\n   *\n   * @param dateString - The date string to parse.\n   * @param template - Optional Luxon format token describing `dateString`.\n   * @param opts - Optional Luxon parsing options (zone, locale, …).\n   * @returns The parsed `DateTime` (use `.isValid` to check the result).\n   *\n   * @see https://moment.github.io/luxon/#/parsing?id=parsing-technical-formats\n   *\n   * @example\n   * ```ts\n   * Text.toDateTime('2026-05-04T09:53:51+03:00')\n   * Text.toDateTime('04.05.2026', 'dd.MM.yyyy')\n   * ```\n   */\n  toDateTime(\n    dateString: string,\n    template?: string,\n    opts?: DateTimeOptions\n  ): DateTime {\n    if (Type.isStringFilled(template)) {\n      return DateTime.fromFormat(dateString, template, opts)\n    }\n\n    return DateTime.fromISO(dateString, opts)\n  }\n\n  /**\n   * Formats a date into the string Bitrix24 expects in REST payloads\n   * (`yyyy-MM-dd'T'HH:mm:ssZZ`, i.e. PHP's `Y-m-d\\TH:i:sP`).\n   *\n   * A string input is passed through unchanged (assumed already formatted); a\n   * JS `Date` is converted through Luxon first.\n   *\n   * @param date - The value to format: an already-formatted string, a JS `Date`,\n   *   or a Luxon `DateTime`.\n   * @returns The Bitrix24-formatted date string.\n   *\n   * @example\n   * ```ts\n   * Text.toB24Format(new Date()) // '2026-05-04T09:53:51+03:00'\n   * ```\n   */\n  toB24Format(\n    date: string | DateTime | Date\n  ): string {\n    if (typeof date === 'string') {\n      return date\n    } else if (date instanceof Date) {\n      return this.toB24Format(DateTime.fromJSDate(date))\n    }\n\n    return date.toFormat('yyyy-MM-dd\\'T\\'HH:mm:ssZZ')\n  }\n\n  /**\n   * Returns the current local timestamp formatted for log lines\n   * (`yyyy-MM-dd HH:mm:ss`).\n   *\n   * @returns The formatted current timestamp.\n   *\n   * @example\n   * ```ts\n   * Text.getDateForLog() // '2026-05-04 09:53:51'\n   * ```\n   */\n  getDateForLog(): string {\n    return DateTime.now().toFormat('yyyy-MM-dd HH:mm:ss')\n  }\n\n  /**\n   * Serialises a plain object into an `application/x-www-form-urlencoded`\n   * query string.\n   *\n   * Keys and values are percent-encoded. Array values are expanded into\n   * indexed pairs (`key[0]=a&key[1]=b`). The leading `?` is **not** included.\n   *\n   * @param params - The object to serialise. A `null` / `undefined` value\n   *   yields an empty string.\n   * @returns The encoded query string (without a leading `?`).\n   *\n   * @example\n   * ```ts\n   * Text.buildQueryString({ id: 7, tag: ['a', 'b'] })\n   * // 'id=7&tag%5B0%5D=a&tag%5B1%5D=b'\n   * ```\n   */\n  buildQueryString(params: any): string {\n    if (Type.isNil(params)) {\n      return ''\n    }\n\n    const pairs: string[] = []\n\n    for (const [key, value] of Object.entries(params)) {\n      if (Type.isArray(value)) {\n        value.forEach((valueElement: any, index: number) => {\n          pairs.push(\n            `${encodeURIComponent(`${key}[${index}]`)}=${encodeURIComponent(valueElement)}`\n          )\n        })\n      } else {\n        pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value as any)}`)\n      }\n    }\n\n    return pairs.join('&')\n  }\n}\n\nexport const Text = new TextManager()\n"],"names":[],"mappings":"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"}