val_highlight_flutter
Syntax-highlighted code for Flutter.
Show code with CodeView and edit it with CodeField.
55 languages, eight themes, and large files that stay smooth.
โ๏ธ Engine ยท ๐ป GitHub ยท ๐ฆ pub.dev
โจ Why val_highlight_flutter?
- Two widgets, one line each โ
CodeView(source, language: dartLanguage)to show code,CodeField(controller: โฆ)to edit it. - Smooth on large files โ a 20,000-line file scrolls with no dropped frames, and typing in a 2,000-line editor takes about 14 ms per keystroke.
- Real editing โ Tab and Shift+Tab indent and outdent, Enter keeps the indentation, and every edit re-highlights only what it can affect.
- Native rendering โ plain Flutter text, no WebView and no platform code. Works on Android, iOS, macOS, Windows, Linux and the web.
- Follows your app โ light and dark themes switch with the app, and
CodeThemesets defaults once for every code block. - Interactive โ tap handlers and custom spans per token, for jump-to-definition, links and tooltips.
๐ ๏ธ Quick start
flutter pub add val_highlight_flutter
import 'package:val_highlight_flutter/val_highlight_flutter.dart';
import 'package:val_highlight/languages/dart.dart';
CodeView(source, language: dartLanguage)
This package re-exports the core API of
val_highlight. Languages and
themes are separate imports under package:val_highlight/languages/ and
package:val_highlight/themes/, so an app ships only what it uses.
๐ CodeView
CodeView(
source,
language: kotlinLanguage,
lineNumbers: true,
highlightedLines: {3, 4},
wrap: true,
header: const Text('MainActivity.kt'),
onTokenTap: (token) => print('${token.scope}: ${token.text}'),
)
- Line numbers โ
lineNumbers,firstLineNumber; a customgutterBuilder. - Highlighted lines โ
highlightedLines,highlightColor. - Wrapping โ
wrap: true, or scroll long lines horizontally. - Selection and copying โ on by default (
selectable); line numbers are never copied. - Custom rendering โ
lineBuilderwraps each row,headeradds a title bar or copy button,spanBuilderreplaces any token's span. - Tappable tokens โ
onTokenTapreceives each token's text, offsets, line and scopes. - Unknown languages โ with no
language, passdetectLanguages: allLanguagesto detect it; otherwise the generic grammar highlights what most languages share (fallbackLanguagechanges this). - Large files โ code with more than
virtualizeAbovelines (1,000 by default), placed where its height is bounded, renders lazily. Inputs above 50,000 characters are highlighted in a background isolate while plain text shows.
โจ๏ธ CodeField
final controller = HighlightTextController(language: dartLanguage);
CodeField(controller: controller, expands: true)
CodeField is a TextField for code:
- monospace, no autocorrect or smart quotes;
- Tab and Shift+Tab indent and outdent (
indentsets the unit); - Enter keeps the current indentation, adding a level after
{,[,(or:; - each edit re-scans only the lines it can affect.
Flutter lays out a text field's whole text on every change, and styled runs
make that slower. So for documents over 300 lines, CodeField colours only
the visible lines plus a margin, and the coloured window follows scrolling.
HighlightTextController also works in a plain TextField for short
documents. For long ones, use CodeField, or set controller.window
yourself.
๐จ Themes
The theme follows the app's brightness: lightTheme or darkTheme by
default. Choose any of the eight built-in themes, a VS Code theme, or your
own:
CodeView(source, language: dartLanguage, theme: midnightTheme)
Set app-wide defaults once:
MaterialApp(
theme: ThemeData(
extensions: [
CodeTheme(
light: sepiaTheme,
dark: dimTheme,
textStyle: const TextStyle(fontFamily: 'JetBrains Mono'),
lineNumbers: true,
),
],
),
)
โ๏ธ CodeHighlighter
CodeHighlighter.shared highlights for every widget, with a result cache.
Create your own to change the isolate threshold or cache size, or to resolve
languages named inside code, such as Markdown fences:
final highlighter = CodeHighlighter(registry: allLanguagesRegistry());
CodeView(markdown, language: markdownLanguage, highlighter: highlighter)
Call CodeHighlighter.shared.preload([dartLanguage, โฆ]) at startup to
compile languages during idle frames, so the first code shown in each has no
compile delay (1โ3 ms per language otherwise).
๐งฑ Lower level
CodeStylesconverts aValThemeinto cachedTextStyles.lineSpans,documentSpansandexactSpansturn aHighlightResultintoTextSpans for your own widgets.
๐ธ Screenshots
![]() CodeView Line numbers, highlighted lines, selection. |
![]() CodeField An editor that highlights as you type. |
![]() Languages inside languages Markdown fences, HTML with CSS and JavaScript. |
|---|
โก Performance
Frame timings on a MacBook, in profile mode:
| Scenario | Build time avg / p90 | Missed frames |
|---|---|---|
Scroll a 20,000-line CodeView |
1.3 / 2.6 ms | 0 of 926 |
| Same, wrapped | 1.3 / 2.6 ms | 0 of 927 |
| Scroll 800 lines as one text block | 0.3 / 0.4 ms | 0 of 915 |
Type in a 2,000-line CodeField |
14.3 / 15.7 ms | 4 of 120 |
Type in a plain TextField, same text, no highlighting |
17.4 / 17.6 ms | 120 of 120 |
Scroll a 2,000-line CodeField |
3.7 / 7.1 ms | 15 of 926 |
The missed frames while scrolling a CodeField happen when its coloured
window moves, which makes Flutter lay out the whole field again.
๐งช Example
The example app has a gallery of every language and theme, a live editor, and a large file rendered lazily.
Built by Val
val_highlight_flutter is part of Val, the live visual
layer for AI agents.
๐ฌ Community
Issues and pull requests are welcome on GitHub; see the contributing guide. If the package helps your project, consider giving it a like on pub.dev or a star on GitHub.
๐ License
BSD 3-Clause โ see LICENSE.
Libraries
- val_highlight_flutter
- Flutter widgets for
val_highlight.


