npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

rn-code-highlighter

v0.1.2

Published

A native, virtualized syntax highlighter for React Native.

Readme

rn-code-highlighter

A native syntax highlighter and live code editor for React Native. Highlight.js performs tokenization locally, and React Native primitives render the result. It does not use a WebView or download runtime assets.

Install

npm install rn-code-highlighter

react and react-native are peer dependencies.

Usage

import { CodeHighlighter } from 'rn-code-highlighter';

export function SourcePreview() {
  return (
    <CodeHighlighter
      code={'const greeting: string = "Hello";'}
      language="typescript"
      theme="dark"
      showLineNumbers
    />
  );
}

CodeHighlighter is an alias of CodeViewer; both names are exported. The component is controlled: when code changes it tokenizes and renders the new value.

Live editor

CodeEditor is a controlled native editor. It uses a multiline TextInput for editing, selection, the caret, keyboard behavior, and accessibility, with syntax-highlighted text rendered underneath.

import React, { useState } from 'react';
import { CodeEditor } from 'rn-code-highlighter';

export function SourceEditor() {
  const [code, setCode] = useState('const answer = 42;');

  return (
    <CodeEditor
      value={code}
      onChangeText={setCode}
      language="typescript"
      theme="dark"
      showLineNumbers
    />
  );
}

The editor supports native selection, two-axis scrolling, line numbers, read-only mode, and standard TextInput behavior through textInputProps. Syntax highlighting falls back to plain text above maxHighlightedCharacters, but the editable value is never truncated. It is intended for source snippets and normal-sized files; use CodeViewer for very large, read-only files because its rows are virtualized.

Customization

Presentation is split into independent style layers, while native input and scroll behavior can be configured with prop bags:

import React, { useRef, useState } from 'react';
import { CodeEditor, type CodeEditorHandle } from 'rn-code-highlighter';

export function CustomizedEditor() {
  const editor = useRef<CodeEditorHandle>(null);
  const [code, setCode] = useState('// Start typing');

  return (
    <CodeEditor
      ref={editor}
      value={code}
      onChangeText={setCode}
      language="typescript"
      style={{ borderRadius: 12 }}
      gutterStyle={{ borderRightWidth: 0 }}
      codeStyle={{ letterSpacing: 0.2 }}
      lineNumberStyle={{ opacity: 0.7 }}
      lineNumberFormatter={(line) => String(line).padStart(3, '0')}
      selectionColor="#4c8dff66"
      textInputProps={{ accessibilityLabel: 'TypeScript source' }}
      verticalScrollViewProps={{ keyboardDismissMode: 'interactive' }}
    />
  );
}

codeStyle is applied to both the highlighted text and transparent input, keeping their glyphs aligned. Use fontFamily, fontSize, and lineHeight for typography metrics. If a custom monospace font has an unusual glyph width, set characterWidth to its measured width. inputStyle is for input-only presentation and editorContentStyle, lineStyle, gutterStyle, and lineNumberStyle target their respective layers.

By default, editor changes pass through normalizeCodeInput: curly/full-width quotes become ASCII code quotes, CRLF becomes LF, and pasted non-breaking spaces become regular spaces. It never trims ordinary spaces or indentation. Pass a custom inputNormalizer, or null to preserve input exactly. On iOS, smartInsertDelete defaults to false to prevent the system from adding a space after paste; it can be re-enabled explicitly.

A CodeEditorHandle ref exposes focus(), blur(), isFocused(), scrollTo(), and the one-based scrollToLine(). The editor also reports calculated dimensions through onContentSizeChange.

Editor props

| Prop | Type | Default | | --- | --- | --- | | value | string | required | | onChangeText | (value: string) => void | required | | language | string | plain text | | theme | "dark" \| "light" \| CodeViewerTheme | "dark" | | showLineNumbers | boolean | true | | lineNumberStart | number | 1 | | lineNumberFormatter | (line: number) => string \| number | String | | editable | boolean | true | | fontFamily | string | platform monospace | | fontSize | number | 14 | | lineHeight | number | 21 | | tabSize | number | 2 | | maxHighlightedCharacters | number | 250000 | | maxContentWidth | number | 100000 | | characterWidth | number | estimated from fontSize | | autoScrollToCaret | boolean | true | | inputNormalizer | ((nextValue, previousValue) => string) \| null | normalizeCodeInput | | smartInsertDelete | boolean | false | | horizontalScrollEnabled | boolean | true | | verticalScrollEnabled | boolean | true | | showsHorizontalScrollIndicator | boolean | true | | showsVerticalScrollIndicator | boolean | true | | bounces | boolean | false | | codeStyle, inputStyle, lineNumberStyle | TextStyle | none | | editorContentStyle, gutterStyle, lineStyle | ViewStyle | none | | textInputProps | TextInputProps | editor-friendly defaults | | horizontalScrollViewProps | ScrollViewProps | editor-friendly defaults | | verticalScrollViewProps | ScrollViewProps | editor-friendly defaults | | onContentSizeChange | (size) => void | none |

Props

| Prop | Type | Default | | --- | --- | --- | | code | string | required | | language | string | plain text | | theme | "dark" \| "light" \| CodeViewerTheme | "dark" | | showLineNumbers | boolean | true | | selectable | boolean | true | | fontFamily | string | platform monospace | | fontSize | number | 11 | | lineHeight | number | 17 | | gutterWidth | number | 48 | | horizontalPadding | number | 10 | | tabSize | number | 2 | | maxHighlightedCharacters | number | 250000 | | maxRenderedCharacters | number | 1000000 | | truncationMessage | string | built-in message |

The viewer falls back to plain text for unknown languages and inputs larger than maxHighlightedCharacters. Rendering is truncated at maxRenderedCharacters.

Exports

  • CodeHighlighter, CodeViewer, CodeEditor, and the default export
  • codeViewerThemes
  • tokenizeCode and normalizeCodeInput
  • default size limits and all public TypeScript types

Development

npm install
npm test
npm run typecheck
npm run build