# Utilities

Utility functions and the bundled Prism instance for advanced usage, custom implementations, and direct access to tokenization functionality.

## Capabilities

### Bundled Prism Instance

Pre-configured Prism.js instance with common programming languages bundled for optimal performance and no global namespace pollution.

```typescript { .api }
/**
 * Pre-configured Prism.js instance with bundled language definitions
 * Includes common programming languages without polluting global namespace
 */
declare const Prism: PrismLib;

interface PrismLib {
  /** Object containing grammar definitions for supported languages */
  languages: Record<string, PrismGrammar>;
  /** Tokenize text using a specific grammar */
  tokenize(text: string, grammar: PrismGrammar): (string | PrismToken)[];
  /** Hook system for extending Prism functionality */
  hooks: {
    /** Run hooks for specific events */
    run(name: string, env: EnvConfig): void;
  };
}

type PrismGrammar = import("prismjs").Grammar;
```

**Supported Languages:**
- **Web**: markup (HTML), jsx, tsx, javascript (via js-extras)
- **Systems**: rust, go, cpp, swift, kotlin, objectivec
- **Functional**: reason
- **Scripting**: python
- **Data**: json, yaml, graphql
- **Documentation**: markdown

**Usage Examples:**

```typescript
import { Prism } from "prism-react-renderer";

// Check if a language is supported
function isLanguageSupported(language: string): boolean {
  return language.toLowerCase() in Prism.languages;
}

// Get available languages
const availableLanguages = Object.keys(Prism.languages);
console.log("Supported languages:", availableLanguages);

// Direct tokenization
const code = "const greeting = 'Hello, World!';";
const grammar = Prism.languages.javascript;
const tokens = Prism.tokenize(code, grammar);

// Use with custom hook implementations
function useCustomTokenizer(code: string, language: string) {
  const grammar = Prism.languages[language.toLowerCase()];
  
  if (!grammar) {
    console.warn(`Grammar not found for language: ${language}`);
    return [code]; // Return as plain text
  }
  
  return Prism.tokenize(code, grammar);
}

// Language fallback handling
function getGrammarWithFallback(language: string): PrismGrammar | null {
  const normalizedLang = language.toLowerCase();
  
  // Direct match
  if (Prism.languages[normalizedLang]) {
    return Prism.languages[normalizedLang];
  }
  
  // Common aliases
  const aliases: Record<string, string> = {
    'js': 'javascript',
    'ts': 'typescript',  
    'py': 'python',
    'md': 'markdown',
    'yml': 'yaml'
  };
  
  const aliasTarget = aliases[normalizedLang];
  if (aliasTarget && Prism.languages[aliasTarget]) {
    return Prism.languages[aliasTarget];
  }
  
  return null;
}
```

### normalizeTokens Function

Utility function that converts Prism's raw token output into a normalized 2D array structure organized by lines.

```typescript { .api }
/**
 * Converts Prism tokens into normalized Token structure grouped by lines
 * Handles nested tokens, newlines, and empty lines consistently
 * @param tokens - Raw tokens from Prism.tokenize()
 * @returns 2D array of normalized tokens organized by lines
 */
declare function normalizeTokens(tokens: (PrismToken | string)[]): Token[][];

interface Token {
  /** Array of token type classifications */
  types: string[];
  /** Token content/text */
  content: string;
  /** Whether this token represents an empty line */
  empty?: boolean;
}
```

**Usage Examples:**

```typescript
import { normalizeTokens, Prism } from "prism-react-renderer";

// Basic normalization
const code = `function greet(name) {
  console.log('Hello, ' + name);
}`;

const grammar = Prism.languages.javascript;
const rawTokens = Prism.tokenize(code, grammar);
const normalizedTokens = normalizeTokens(rawTokens);

console.log(normalizedTokens);
// [
//   [{ types: ['keyword'], content: 'function' }, { types: ['plain'], content: ' ' }, ...],
//   [{ types: ['plain'], content: '  ' }, { types: ['builtin'], content: 'console' }, ...],
//   [{ types: ['punctuation'], content: '}' }]
// ]

// Handle empty lines
const codeWithEmptyLines = `const a = 1;

const b = 2;`;

const tokensWithEmpty = normalizeTokens(Prism.tokenize(codeWithEmptyLines, grammar));
// Second array will contain: [{ types: ['plain'], content: '\n', empty: true }]

// Custom rendering with normalized tokens
function renderTokens(tokens: Token[][]) {
  return tokens.map((line, lineIndex) => (
    <div key={lineIndex} className="code-line">
      {line.map((token, tokenIndex) => (
        <span
          key={tokenIndex}
          className={token.types.join(' ')}
          data-empty={token.empty || undefined}
        >
          {token.content}
        </span>
      ))}
    </div>
  ));
}
```


## Advanced Usage Patterns

### Custom Language Support

For languages not included in the bundle, you can extend Prism:

```typescript
import { Prism } from "prism-react-renderer";

// Note: This requires additional Prism language definitions
// You would need to import and register the language manually

// Example of how to check and handle unsupported languages
function highlightWithFallback(code: string, language: string) {
  const grammar = Prism.languages[language.toLowerCase()];
  
  if (!grammar) {
    // Fallback to plain text
    return normalizeTokens([code]);
  }
  
  const tokens = Prism.tokenize(code, grammar);
  return normalizeTokens(tokens);
}
```

### Performance Optimization

```typescript
import { useTokenize, Prism } from "prism-react-renderer";
import { useMemo } from "react";

function OptimizedHighlighter({ code, language }) {
  // Grammar lookup is memoized
  const grammar = useMemo(() => {
    return Prism.languages[language.toLowerCase()];
  }, [language]);
  
  // useTokenize already includes memoization
  const tokens = useTokenize({
    prism: Prism,
    code,
    language,
    grammar
  });
  
  return (
    <div>
      {tokens.map((line, i) => (
        <div key={i}>
          {line.map((token, j) => (
            <span key={j} className={token.types.join(' ')}>
              {token.content}
            </span>
          ))}
        </div>
      ))}
    </div>
  );
}
```

## Supporting Types

```typescript { .api }
type Language = string;
type PrismGrammar = import("prismjs").Grammar;
type PrismLib = typeof import("prismjs");
```