From a7e752d570ce7f3575162846230ef73226e8e906 Mon Sep 17 00:00:00 2001 From: hacker1024 Date: Wed, 22 Jun 2022 23:25:46 +1000 Subject: [PATCH 1/2] fix: Cache generated spans across rebuilds --- flutter_highlight/lib/flutter_highlight.dart | 63 ++++++++++++++------ 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/flutter_highlight/lib/flutter_highlight.dart b/flutter_highlight/lib/flutter_highlight.dart index 9afbc47..775d1f8 100644 --- a/flutter_highlight/lib/flutter_highlight.dart +++ b/flutter_highlight/lib/flutter_highlight.dart @@ -3,7 +3,7 @@ import 'package:flutter/widgets.dart'; import 'package:highlight/highlight.dart' show highlight, Node; /// Highlight Flutter Widget -class HighlightView extends StatelessWidget { +class HighlightView extends StatefulWidget { /// The original code to be highlighted final String source; @@ -36,6 +36,22 @@ class HighlightView extends StatelessWidget { int tabSize = 8, // TODO: https://github.com/flutter/flutter/issues/50087 }) : source = input.replaceAll('\t', ' ' * tabSize); + static const _rootKey = 'root'; + static const _defaultFontColor = Color(0xff000000); + static const _defaultBackgroundColor = Color(0xffffffff); + + // TODO: dart:io is not available at web platform currently + // See: https://github.com/flutter/flutter/issues/39998 + // So we just use monospace here for now + static const _defaultFontFamily = 'monospace'; + + @override + State createState() => _HighlightViewState(); +} + +class _HighlightViewState extends State { + late List _spans; + List _convert(List nodes) { List spans = []; var currentSpans = spans; @@ -45,10 +61,11 @@ class HighlightView extends StatelessWidget { if (node.value != null) { currentSpans.add(node.className == null ? TextSpan(text: node.value) - : TextSpan(text: node.value, style: theme[node.className!])); + : TextSpan(text: node.value, style: widget.theme[node.className!])); } else if (node.children != null) { List tmp = []; - currentSpans.add(TextSpan(children: tmp, style: theme[node.className!])); + currentSpans + .add(TextSpan(children: tmp, style: widget.theme[node.className!])); stack.add(currentSpans); currentSpans = tmp; @@ -68,32 +85,44 @@ class HighlightView extends StatelessWidget { return spans; } - static const _rootKey = 'root'; - static const _defaultFontColor = Color(0xff000000); - static const _defaultBackgroundColor = Color(0xffffffff); + void _generateSpans() => _spans = _convert( + highlight.parse(widget.source, language: widget.language).nodes!); - // TODO: dart:io is not available at web platform currently - // See: https://github.com/flutter/flutter/issues/39998 - // So we just use monospace here for now - static const _defaultFontFamily = 'monospace'; + @override + void initState() { + super.initState(); + _generateSpans(); + } + + @override + void didUpdateWidget(HighlightView oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.source != oldWidget.source || + widget.language != oldWidget.language || + widget.theme != oldWidget.theme) { + _generateSpans(); + } + } @override Widget build(BuildContext context) { var _textStyle = TextStyle( - fontFamily: _defaultFontFamily, - color: theme[_rootKey]?.color ?? _defaultFontColor, + fontFamily: HighlightView._defaultFontFamily, + color: widget.theme[HighlightView._rootKey]?.color ?? + HighlightView._defaultFontColor, ); - if (textStyle != null) { - _textStyle = _textStyle.merge(textStyle); + if (widget.textStyle != null) { + _textStyle = _textStyle.merge(widget.textStyle); } return Container( - color: theme[_rootKey]?.backgroundColor ?? _defaultBackgroundColor, - padding: padding, + color: widget.theme[HighlightView._rootKey]?.backgroundColor ?? + HighlightView._defaultBackgroundColor, + padding: widget.padding, child: RichText( text: TextSpan( style: _textStyle, - children: _convert(highlight.parse(source, language: language).nodes!), + children: _spans, ), ), ); From 9ba389f462eab2f5ac8b8e3af59bb5f29a296ab3 Mon Sep 17 00:00:00 2001 From: hacker1024 Date: Wed, 22 Jun 2022 23:32:17 +1000 Subject: [PATCH 2/2] fix: Don't regenerate nodes on a theme change --- flutter_highlight/lib/flutter_highlight.dart | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/flutter_highlight/lib/flutter_highlight.dart b/flutter_highlight/lib/flutter_highlight.dart index 775d1f8..fd843ed 100644 --- a/flutter_highlight/lib/flutter_highlight.dart +++ b/flutter_highlight/lib/flutter_highlight.dart @@ -50,6 +50,7 @@ class HighlightView extends StatefulWidget { } class _HighlightViewState extends State { + late List _nodes; late List _spans; List _convert(List nodes) { @@ -85,12 +86,15 @@ class _HighlightViewState extends State { return spans; } - void _generateSpans() => _spans = _convert( - highlight.parse(widget.source, language: widget.language).nodes!); + void _parse() => + _nodes = highlight.parse(widget.source, language: widget.language).nodes!; + + void _generateSpans() => _spans = _convert(_nodes); @override void initState() { super.initState(); + _parse(); _generateSpans(); } @@ -98,8 +102,10 @@ class _HighlightViewState extends State { void didUpdateWidget(HighlightView oldWidget) { super.didUpdateWidget(oldWidget); if (widget.source != oldWidget.source || - widget.language != oldWidget.language || - widget.theme != oldWidget.theme) { + widget.language != oldWidget.language) { + _parse(); + _generateSpans(); + } else if (widget.theme != oldWidget.theme) { _generateSpans(); } }