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.flutter-io.cn
β¨ 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.flutter-io.cn or a star on GitHub.
π License
BSD 3-Clause β see LICENSE.
Libraries
- val_highlight_flutter
- Flutter widgets for
val_highlight.


