or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

collections.mdform-utilities.mdindex.mdobject-operations.mdreactive-patterns.mdstring-processing.mdtype-checking.mdvalidation.md
tile.json

string-processing.mddocs/

String Processing

String manipulation utilities including case conversion and length calculation with ANSI code and Unicode support. These functions are essential for form field processing, data transformation, and internationalization.

Capabilities

String Length Calculation

Advanced string length calculation that handles ANSI escape codes and Unicode properly.

/**
 * Calculate the visual length of a string, excluding ANSI escape codes and handling Unicode correctly
 * @param input - String to measure
 * @returns Visual length of the string
 */
function stringLength(input: string): number;

Usage Examples:

import { stringLength } from "@formily/shared";

// Basic string length
console.log(stringLength("hello"));        // 5

// ANSI escape codes are excluded from length
const coloredText = "\x1b[31mRed Text\x1b[0m";  // Red colored text
console.log(coloredText.length);           // 18 (includes ANSI codes)
console.log(stringLength(coloredText));    // 8 (visual length only)

// Unicode characters (astral characters) handled correctly  
const emoji = "👨‍💻"; // Man technologist emoji (composite character)
console.log(emoji.length);                // 5 (JavaScript counts code units)
console.log(stringLength(emoji));         // 1 (visual length)

const mixedUnicode = "Hello 👋 World 🌍";
console.log(mixedUnicode.length);          // 15
console.log(stringLength(mixedUnicode));   // 13 (correct visual length)

// Complex terminal output
const terminalOutput = "\x1b[32m✓\x1b[0m Success: \x1b[1mBuild completed\x1b[0m";
console.log(stringLength(terminalOutput)); // Visual length without color codes

Case Conversion

Comprehensive case conversion utilities for different naming conventions.

/**
 * Convert string to camelCase
 * @param str - String to convert
 * @returns String in camelCase format
 */
function camelCase(str: string): string;

/**
 * Convert string to PascalCase
 * @param str - String to convert  
 * @returns String in PascalCase format
 */
function pascalCase(str: string): string;

/**
 * Convert string to param-case (kebab-case)
 * @param str - String to convert
 * @returns String in param-case format
 */
function paramCase(str: string): string;

/**
 * Convert string to lower case
 * @param str - String to convert
 * @returns String in lower case
 */
function lowerCase(str: string): string;

/**
 * Convert string to UPPER CASE
 * @param str - String to convert
 * @returns String in upper case
 */
function upperCase(str: string): string;

Usage Examples:

import { 
  camelCase, pascalCase, paramCase, 
  lowerCase, upperCase 
} from "@formily/shared";

// Basic case conversion
const input = "hello-world_example";

console.log(camelCase(input));    // "helloWorldExample"
console.log(pascalCase(input));   // "HelloWorldExample"  
console.log(paramCase(input));    // "hello-world-example"
console.log(lowerCase(input));    // "hello world example"
console.log(upperCase(input));    // "HELLO WORLD EXAMPLE"

// Form field name conversion
const formFields = [
  "first-name",
  "last_name", 
  "email-address",
  "phone_number"
];

// Convert to camelCase for JavaScript
const jsFields = formFields.map(camelCase);
// Result: ["firstName", "lastName", "emailAddress", "phoneNumber"]

// Convert to param-case for HTML attributes
const htmlAttrs = jsFields.map(paramCase);
// Result: ["first-name", "last-name", "email-address", "phone-number"]

// API response transformation
function transformApiResponse(data: Record<string, any>): Record<string, any> {
  const transformed: Record<string, any> = {};
  
  for (const [key, value] of Object.entries(data)) {
    // Convert snake_case API keys to camelCase
    const camelKey = camelCase(key);
    transformed[camelKey] = value;
  }
  
  return transformed;
}

// Usage
const apiData = {
  user_id: 123,
  first_name: "John",
  last_name: "Doe", 
  email_address: "john@example.com"
};

const jsData = transformApiResponse(apiData);
/*
Result: {
  userId: 123,
  firstName: "John",
  lastName: "Doe",
  emailAddress: "john@example.com"
}
*/

Advanced String Processing Examples

import { camelCase, paramCase, stringLength } from "@formily/shared";

// Form validation with proper length checking
function validateFormField(value: string, maxLength: number): boolean {
  // Use stringLength for accurate character counting
  return stringLength(value) <= maxLength;
}

// Handles Unicode properly
const unicodeInput = "Café 🌟 München"; // Contains accented chars and emoji
console.log(validateFormField(unicodeInput, 15)); // true (visual length: 13)

// CSS class name generation
function generateCSSClassName(componentName: string, modifier?: string): string {
  const baseClass = paramCase(componentName);
  
  if (modifier) {
    return `${baseClass}--${paramCase(modifier)}`;
  }
  
  return baseClass;
}

// Usage
console.log(generateCSSClassName("FormInput"));              // "form-input"
console.log(generateCSSClassName("FormInput", "isDisabled")); // "form-input--is-disabled"

// Database column to JavaScript property mapping
function mapDatabaseColumns(rows: Record<string, any>[]): Record<string, any>[] {
  return rows.map(row => {
    const mappedRow: Record<string, any> = {};
    
    for (const [column, value] of Object.entries(row)) {
      // Convert database snake_case to JavaScript camelCase
      mappedRow[camelCase(column)] = value;
    }
    
    return mappedRow;
  });
}

// Usage
const dbRows = [
  { user_id: 1, first_name: "Alice", created_at: "2023-01-01" },
  { user_id: 2, first_name: "Bob", created_at: "2023-01-02" }
];

const jsRows = mapDatabaseColumns(dbRows);
/*
Result: [
  { userId: 1, firstName: "Alice", createdAt: "2023-01-01" },
  { userId: 2, firstName: "Bob", createdAt: "2023-01-02" }
]
*/

// URL slug generation
function createUrlSlug(title: string): string {
  return paramCase(title)
    .replace(/[^a-z0-9-]/g, '') // Remove non-alphanumeric except hyphens
    .replace(/-+/g, '-')        // Collapse multiple hyphens
    .replace(/^-|-$/g, '');     // Remove leading/trailing hyphens
}

// Usage
console.log(createUrlSlug("My Blog Post Title!"));  // "my-blog-post-title"
console.log(createUrlSlug("Hello   World???"));     // "hello-world"

// Configuration key normalization
function normalizeConfigKeys(config: Record<string, any>, format: 'camel' | 'param' = 'camel'): Record<string, any> {
  const normalized: Record<string, any> = {};
  const converter = format === 'camel' ? camelCase : paramCase;
  
  for (const [key, value] of Object.entries(config)) {
    const normalizedKey = converter(key);
    
    if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
      // Recursively normalize nested objects
      normalized[normalizedKey] = normalizeConfigKeys(value, format);
    } else {
      normalized[normalizedKey] = value;
    }
  }
  
  return normalized;
}

// Usage
const rawConfig = {
  "database-host": "localhost",
  "database_port": 5432,
  "api_settings": {
    "max_connections": 100,
    "timeout-seconds": 30
  }
};

const camelConfig = normalizeConfigKeys(rawConfig, 'camel');
/*
Result: {
  databaseHost: "localhost",
  databasePort: 5432,
  apiSettings: {
    maxConnections: 100,
    timeoutSeconds: 30
  }
}
*/

const paramConfig = normalizeConfigKeys(rawConfig, 'param');
/*
Result: {
  "database-host": "localhost",
  "database-port": 5432,
  "api-settings": {
    "max-connections": 100,
    "timeout-seconds": 30
  }
}
*/

Implementation Notes

The string processing utilities in @formily/shared use well-tested external libraries for case conversion:

  • camelCase: Uses the camel-case library
  • pascalCase: Uses the pascal-case library
  • paramCase: Uses the param-case library
  • lowerCase: Uses the lower-case library
  • upperCase: Uses the upper-case library

The stringLength function includes:

  • ANSI escape code removal: Strips terminal color codes and formatting
  • Astral character handling: Properly counts Unicode characters that span multiple code units
  • Cross-platform compatibility: Works consistently across different JavaScript environments

These utilities are particularly useful for:

  • Form field processing and validation
  • API data transformation between naming conventions
  • CSS class name generation
  • URL slug creation
  • Database column mapping
  • Configuration file processing
  • Internationalization and Unicode text handling