CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-syntax-highlighter

React component library for syntax highlighting with highlight.js and Prism.js support.

Pending
Overview
Eval results
Files

async-builds.mddocs/

Async Build Variants

Asynchronous syntax highlighter builds with dynamic language loading and code splitting support. These builds defer loading of the syntax highlighting engine and languages until needed, optimizing initial bundle size and rendering performance.

Capabilities

LightAsync (Highlight.js Async)

Async light build using highlight.js with dynamic language loading.

/**
 * Async syntax highlighter component using highlight.js
 * Supports dynamic loading of languages and the core highlighter
 */
const LightAsync: React.ComponentType<SyntaxHighlighterProps> & {
  /** Preload the AST generator (highlight.js core) */
  preload: () => Promise<void>;
  /** Load a specific language definition */
  loadLanguage: (language: string) => Promise<void>;
  /** Check if a language is supported by available loaders */
  isSupportedLanguage: (language: string) => boolean;
  /** Check if a language is currently registered */
  isRegistered: (language: string) => boolean;
  /** Register a language definition manually */
  registerLanguage: (name: string, language: any) => void;
  /** Array of supported language identifiers */
  supportedLanguages: string[];
};

Usage Examples:

import { LightAsync as SyntaxHighlighter } from 'react-syntax-highlighter';

// Basic usage - languages load automatically
const AsyncExample = () => {
  const code = `async function fetchData(url) {
  const response = await fetch(url);
  return response.json();
}`;

  return (
    <SyntaxHighlighter language="javascript">
      {code}
    </SyntaxHighlighter>
  );
};

// Preload for immediate highlighting
const PreloadExample = () => {
  React.useEffect(() => {
    SyntaxHighlighter.preload();
  }, []);

  return (
    <SyntaxHighlighter language="python">
      {pythonCode}
    </SyntaxHighlighter>
  );
};

// Manual language loading
const ManualLoadExample = () => {
  const [isReady, setIsReady] = React.useState(false);

  React.useEffect(() => {
    const loadLanguage = async () => {
      await SyntaxHighlighter.loadLanguage('rust');
      setIsReady(true);
    };
    loadLanguage();
  }, []);

  if (!isReady) return <div>Loading syntax highlighter...</div>;

  return (
    <SyntaxHighlighter language="rust">
      {rustCode}
    </SyntaxHighlighter>
  );
};

PrismAsync (Prism.js Async)

Async build using Prism.js with dynamic language loading.

/**
 * Async syntax highlighter component using Prism.js
 */
const PrismAsync: React.ComponentType<SyntaxHighlighterProps> & {
  /** Preload the AST generator (refractor core) */
  preload: () => Promise<void>;
  /** Load a specific language definition */
  loadLanguage: (language: string) => Promise<void>;
  /** Check if a language is supported by available loaders */
  isSupportedLanguage: (language: string) => boolean;
  /** Check if a language is currently registered */
  isRegistered: (language: string) => boolean;
  /** Register a language definition manually */
  registerLanguage: (name: string, language: any) => void;
  /** Array of supported language identifiers */
  supportedLanguages: string[];
};

Usage Examples:

import { PrismAsync as SyntaxHighlighter } from 'react-syntax-highlighter';

// JSX highlighting with Prism async
const JSXExample = () => {
  const jsxCode = `const Button = ({ onClick, children }) => (
  <button
    className="btn btn-primary"
    onClick={onClick}
  >
    {children}
  </button>
);

export default Button;`;

  return (
    <SyntaxHighlighter language="jsx">
      {jsxCode}
    </SyntaxHighlighter>
  );
};

PrismAsyncLight

Async light build combining Prism.js with minimal core loading.

/**
 * Async light syntax highlighter component using Prism.js core
 */
const PrismAsyncLight: React.ComponentType<SyntaxHighlighterProps> & {
  /** Preload the AST generator (refractor core) */
  preload: () => Promise<void>;
  /** Load a specific language definition */
  loadLanguage: (language: string) => Promise<void>;
  /** Check if a language is supported by available loaders */
  isSupportedLanguage: (language: string) => boolean;
  /** Check if a language is currently registered */
  isRegistered: (language: string) => boolean;
  /** Register a language definition manually */
  registerLanguage: (name: string, language: any) => void;
  /** Array of supported language identifiers */
  supportedLanguages: string[];
};

Async Methods

Dynamic loading and management methods available on async components.

/**
 * Preload the core syntax highlighting engine
 * @returns Promise that resolves when the engine is loaded
 */
preload(): Promise<void>;

/**
 * Load a specific language definition
 * @param language - Language identifier to load
 * @returns Promise that resolves when language is loaded
 */
loadLanguage(language: string): Promise<void>;

/**
 * Check if a language is supported by the async loader
 * @param language - Language identifier to check
 * @returns True if language can be loaded
 */
isSupportedLanguage(language: string): boolean;

/**
 * Check if a language is currently registered and ready for use
 * @param language - Language identifier to check
 * @returns True if language is registered
 */
isRegistered(language: string): boolean;

/**
 * Manually register a language definition
 * @param name - Language identifier
 * @param language - Language definition module
 */
registerLanguage(name: string, language: any): void;

Advanced Usage Examples:

import { LightAsync as SyntaxHighlighter } from 'react-syntax-highlighter';

// Check language support
const AdvancedExample = () => {
  const [language, setLanguage] = React.useState('javascript');
  const [isSupported, setIsSupported] = React.useState(false);

  React.useEffect(() => {
    const checkSupport = async () => {
      const supported = SyntaxHighlighter.isSupportedLanguage(language);
      setIsSupported(supported);
      
      if (supported && !SyntaxHighlighter.isRegistered(language)) {
        await SyntaxHighlighter.loadLanguage(language);
      }
    };
    
    checkSupport();
  }, [language]);

  if (!isSupported) {
    return <pre>{code}</pre>; // Fallback to plain text
  }

  return (
    <SyntaxHighlighter language={language}>
      {code}
    </SyntaxHighlighter>
  );
};

// Bulk language preloading
const BulkPreloadExample = () => {
  React.useEffect(() => {
    const preloadLanguages = async () => {
      const languages = ['javascript', 'python', 'java', 'cpp'];
      
      // Preload core first
      await SyntaxHighlighter.preload();
      
      // Load languages in parallel
      await Promise.all(
        languages.map(lang => SyntaxHighlighter.loadLanguage(lang))
      );
    };
    
    preloadLanguages();
  }, []);

  return (
    <div>
      {codeBlocks.map((block, index) => (
        <SyntaxHighlighter key={index} language={block.language}>
          {block.code}
        </SyntaxHighlighter>
      ))}
    </div>
  );
};

Loading States and Error Handling

Managing loading states and handling errors in async components.

const AsyncWithLoadingState = ({ language, code }) => {
  const [isLoading, setIsLoading] = React.useState(true);
  const [error, setError] = React.useState(null);

  React.useEffect(() => {
    const loadHighlighter = async () => {
      try {
        setIsLoading(true);
        setError(null);
        
        if (!SyntaxHighlighter.isRegistered(language)) {
          await SyntaxHighlighter.loadLanguage(language);
        }
      } catch (err) {
        setError(err.message);
      } finally {
        setIsLoading(false);
      }
    };

    loadHighlighter();
  }, [language]);

  if (error) {
    return (
      <pre style={{ color: 'red' }}>
        Error loading syntax highlighter: {error}
      </pre>
    );
  }

  if (isLoading) {
    return (
      <pre style={{ opacity: 0.5 }}>
        {code} {/* Show code while loading highlighter */}
      </pre>
    );
  }

  return (
    <SyntaxHighlighter language={language}>
      {code}
    </SyntaxHighlighter>
  );
};

Bundle Splitting Benefits

Understanding the performance benefits of async builds.

// Bundle size comparison:
// Standard build: ~500KB (all languages + engine)
// Light build: ~50KB (core only, manual registration)
// Async build: ~5KB initial + chunks loaded on demand

// Async loading pattern
const LazyCodeBlock = React.lazy(async () => {
  // This entire component and its dependencies load on demand
  const { LightAsync as SyntaxHighlighter } = await import('react-syntax-highlighter');
  
  return {
    default: ({ language, children }) => (
      <SyntaxHighlighter language={language}>
        {children}
      </SyntaxHighlighter>
    )
  };
});

// Usage with Suspense
const App = () => (
  <div>
    <h1>My App</h1>
    <React.Suspense fallback={<div>Loading code highlighter...</div>}>
      <LazyCodeBlock language="javascript">
        {codeString}
      </LazyCodeBlock>
    </React.Suspense>
  </div>
);

Integration with Code Splitting

Optimal patterns for code splitting with async builds.

// Route-based code splitting with syntax highlighting
const DocumentationPage = React.lazy(() => import('./DocumentationPage'));

// DocumentationPage.js
import { PrismAsync as SyntaxHighlighter } from 'react-syntax-highlighter';

const DocumentationPage = () => {
  // Preload on route entry
  React.useEffect(() => {
    SyntaxHighlighter.preload();
  }, []);

  return (
    <div>
      <h1>API Documentation</h1>
      {apiExamples.map(example => (
        <SyntaxHighlighter 
          key={example.id} 
          language={example.language}
        >
          {example.code}
        </SyntaxHighlighter>
      ))}
    </div>
  );
};

// App routing
const App = () => (
  <Router>
    <Routes>
      <Route path="/" element={<HomePage />} />
      <Route 
        path="/docs" 
        element={
          <React.Suspense fallback={<div>Loading...</div>}>
            <DocumentationPage />
          </React.Suspense>
        } 
      />
    </Routes>
  </Router>
);

Best Practices

Performance Optimization

// Optimize async loading with caching
class AsyncHighlighterManager {
  constructor() {
    this.loadingPromises = new Map();
    this.loadedLanguages = new Set();
  }

  async ensureLanguage(language) {
    if (this.loadedLanguages.has(language)) {
      return; // Already loaded
    }

    if (this.loadingPromises.has(language)) {
      return this.loadingPromises.get(language); // Loading in progress
    }

    const promise = SyntaxHighlighter.loadLanguage(language)
      .then(() => {
        this.loadedLanguages.add(language);
        this.loadingPromises.delete(language);
      })
      .catch((error) => {
        this.loadingPromises.delete(language);
        throw error;
      });

    this.loadingPromises.set(language, promise);
    return promise;
  }
}

const manager = new AsyncHighlighterManager();

// Usage in components
const CodeBlock = ({ language, children }) => {
  const [isReady, setIsReady] = React.useState(false);

  React.useEffect(() => {
    manager.ensureLanguage(language).then(() => setIsReady(true));
  }, [language]);

  return isReady ? (
    <SyntaxHighlighter language={language}>
      {children}
    </SyntaxHighlighter>
  ) : (
    <pre>{children}</pre>
  );
};

Install with Tessl CLI

npx tessl i tessl/npm-react-syntax-highlighter

docs

async-builds.md

index.md

language-support.md

light-builds.md

prism-integration.md

standard-highlighter.md

styling-themes.md

tile.json