From e22e516b5303d3dfb9660f4e827dd7edaca8f366 Mon Sep 17 00:00:00 2001 From: wangtao Date: Sat, 5 Oct 2024 15:55:08 +0800 Subject: [PATCH] Adding colour to code with the highlight extension --- .../fleather/lib/src/widgets/code_color.dart | 92 +++++++++++++++++++ .../fleather/lib/src/widgets/text_line.dart | 7 +- packages/fleather/pubspec.yaml | 1 + 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 packages/fleather/lib/src/widgets/code_color.dart diff --git a/packages/fleather/lib/src/widgets/code_color.dart b/packages/fleather/lib/src/widgets/code_color.dart new file mode 100644 index 00000000..ac1768d3 --- /dev/null +++ b/packages/fleather/lib/src/widgets/code_color.dart @@ -0,0 +1,92 @@ +import 'package:flutter/widgets.dart'; +import 'package:highlight/highlight.dart' show highlight, Node; + +/// use highlight to color the code +/// the default theme is github theme +class CodeColor { + static const _rootKey = 'root'; + static const _defaultFontColor = Color(0xff000000); + + TextSpan textSpan(String source) { + var theme = githubTheme; + var textStyle = TextStyle( + color: theme[_rootKey]?.color ?? _defaultFontColor, + ); + + return TextSpan( + style: textStyle, + children: + _convert(highlight.parse(source, language: 'dart').nodes!, theme), + ); + } + + List _convert(List nodes, Map theme) { + List spans = []; + var currentSpans = spans; + List> stack = []; + + void traverse(Node node) { + if (node.value != null) { + currentSpans.add(node.className == null + ? TextSpan(text: node.value) + : TextSpan(text: node.value, style: theme[node.className!])); + } else if (node.children != null) { + List tmp = []; + currentSpans + .add(TextSpan(children: tmp, style: theme[node.className!])); + stack.add(currentSpans); + currentSpans = tmp; + + for (var n in node.children!) { + traverse(n); + if (n == node.children!.last) { + currentSpans = stack.isEmpty ? spans : stack.removeLast(); + } + } + } + } + + for (var node in nodes) { + traverse(node); + } + + return spans; + } +} + +const githubTheme = { + 'root': + TextStyle(color: Color(0xff333333), backgroundColor: Color(0xfff8f8f8)), + 'comment': TextStyle(color: Color(0xff999988), fontStyle: FontStyle.italic), + 'quote': TextStyle(color: Color(0xff999988), fontStyle: FontStyle.italic), + 'keyword': TextStyle(color: Color(0xff333333), fontWeight: FontWeight.bold), + 'selector-tag': + TextStyle(color: Color(0xff333333), fontWeight: FontWeight.bold), + 'subst': TextStyle(color: Color(0xff333333), fontWeight: FontWeight.normal), + 'number': TextStyle(color: Color(0xff008080)), + 'literal': TextStyle(color: Color(0xff008080)), + 'variable': TextStyle(color: Color(0xff008080)), + 'template-variable': TextStyle(color: Color(0xff008080)), + 'string': TextStyle(color: Color(0xffdd1144)), + 'doctag': TextStyle(color: Color(0xffdd1144)), + 'title': TextStyle(color: Color(0xff990000), fontWeight: FontWeight.bold), + 'section': TextStyle(color: Color(0xff990000), fontWeight: FontWeight.bold), + 'selector-id': + TextStyle(color: Color(0xff990000), fontWeight: FontWeight.bold), + 'type': TextStyle(color: Color(0xff445588), fontWeight: FontWeight.bold), + 'tag': TextStyle(color: Color(0xff000080), fontWeight: FontWeight.normal), + 'name': TextStyle(color: Color(0xff000080), fontWeight: FontWeight.normal), + 'attribute': + TextStyle(color: Color(0xff000080), fontWeight: FontWeight.normal), + 'regexp': TextStyle(color: Color(0xff009926)), + 'link': TextStyle(color: Color(0xff009926)), + 'symbol': TextStyle(color: Color(0xff990073)), + 'bullet': TextStyle(color: Color(0xff990073)), + 'built_in': TextStyle(color: Color(0xff0086b3)), + 'builtin-name': TextStyle(color: Color(0xff0086b3)), + 'meta': TextStyle(color: Color(0xff999999), fontWeight: FontWeight.bold), + 'deletion': TextStyle(backgroundColor: Color(0xffffdddd)), + 'addition': TextStyle(backgroundColor: Color(0xffddffdd)), + 'emphasis': TextStyle(fontStyle: FontStyle.italic), + 'strong': TextStyle(fontWeight: FontWeight.bold), +}; diff --git a/packages/fleather/lib/src/widgets/text_line.dart b/packages/fleather/lib/src/widgets/text_line.dart index 566120b6..bc4aa062 100644 --- a/packages/fleather/lib/src/widgets/text_line.dart +++ b/packages/fleather/lib/src/widgets/text_line.dart @@ -13,6 +13,7 @@ import 'keyboard_listener.dart'; import 'link.dart'; import 'rich_text_proxy.dart'; import 'theme.dart'; +import 'code_color.dart'; /// Line of text in Fleather editor. /// @@ -172,8 +173,12 @@ class _TextLineState extends State { final text = segment as TextNode; final attrs = text.style; final isLink = attrs.contains(ParchmentAttribute.link); + bool isCodeBlock = widget.node.style.get(ParchmentAttribute.block) == + ParchmentAttribute.block.code; + return TextSpan( - text: text.value, + text: isCodeBlock ? null : text.value, + children: isCodeBlock ? [CodeColor().textSpan(text.value)] : [], style: _getInlineTextStyle(attrs, widget.node.style, theme), recognizer: isLink && canLaunchLinks ? _getRecognizer(segment) : null, mouseCursor: isLink && canLaunchLinks ? SystemMouseCursors.click : null, diff --git a/packages/fleather/pubspec.yaml b/packages/fleather/pubspec.yaml index 3f198a32..bf8269c7 100644 --- a/packages/fleather/pubspec.yaml +++ b/packages/fleather/pubspec.yaml @@ -28,6 +28,7 @@ dependencies: parchment_delta: ^1.0.0 parchment: ^1.19.0 intl: ^0.19.0 + highlight: ^0.7.0 dependency_overrides: parchment: