@bitrix24/b24jssdk
Version:
Bitrix24 REST API JavaScript SDK
1 lines • 22.6 kB
Source Map (JSON)
{"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 '&': '&',\n '<': '<',\n '>': '>',\n '\\'': ''',\n '\"': '"'\n}\n\nconst unescapeEntities: Record<string, string> = {\n '&': '&',\n '&': '&',\n '<': '<',\n '<': '<',\n '>': '>',\n '>': '>',\n '&apos': '\\'',\n ''': '\\'',\n '"': '\"',\n '"': '\"'\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 (`&` instead of `&`). 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>') // '<b>Tom & Jerry</b>'\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 (`&`, `<`, …) and their numeric equivalents\n * (`&`, `<`, …) 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 (`&` 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('<b>Tom & Jerry</b>') // '<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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"}