mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-01 19:12:31 +08:00
feat: Support inline code blocks on markdown rich text (#3186)
Support inline code blocks on markdown rich text.
This commit is contained in:
@ -58,14 +58,24 @@ class RichTextExample extends FlameGame {
|
||||
PlainTextNode('."'),
|
||||
]),
|
||||
]),
|
||||
ParagraphNode.simple(
|
||||
'He pushed the thought under instantly. The fallacy was obvious. It '
|
||||
'presupposed that somewhere or other, outside oneself, there was a '
|
||||
'"real" world where "real" things happened. But how could there be '
|
||||
'such a world? What knowledge have we of anything, save through our '
|
||||
'own minds? All happenings are in the mind. Whatever happens in all '
|
||||
'minds, truly happens.',
|
||||
),
|
||||
ParagraphNode.group([
|
||||
PlainTextNode(
|
||||
'He pushed the thought under instantly. The fallacy was obvious. It '
|
||||
'presupposed that somewhere or other, outside oneself, there was a '
|
||||
'"',
|
||||
),
|
||||
CodeTextNode.simple('real'),
|
||||
PlainTextNode(
|
||||
'" world where "',
|
||||
),
|
||||
CodeTextNode.simple('real'),
|
||||
PlainTextNode(
|
||||
'" things happened. But how could there be '
|
||||
'such a world? What knowledge have we of anything, save through our '
|
||||
'own minds? All happenings are in the mind. Whatever happens in all '
|
||||
'minds, truly happens.',
|
||||
),
|
||||
]),
|
||||
]);
|
||||
|
||||
add(
|
||||
|
||||
24
packages/flame/lib/src/text/nodes/code_text_node.dart
Normal file
24
packages/flame/lib/src/text/nodes/code_text_node.dart
Normal file
@ -0,0 +1,24 @@
|
||||
import 'package:flame/src/text/nodes/inline_text_node.dart';
|
||||
import 'package:flame/text.dart';
|
||||
|
||||
class CodeTextNode extends InlineTextNode {
|
||||
CodeTextNode(this.child);
|
||||
|
||||
CodeTextNode.simple(String text) : child = PlainTextNode(text);
|
||||
|
||||
CodeTextNode.group(List<InlineTextNode> children)
|
||||
: child = GroupTextNode(children);
|
||||
|
||||
final InlineTextNode child;
|
||||
|
||||
static final defaultStyle = InlineTextStyle(fontFamily: 'monospace');
|
||||
|
||||
@override
|
||||
void fillStyles(DocumentStyle stylesheet, InlineTextStyle parentTextStyle) {
|
||||
style = FlameTextStyle.merge(parentTextStyle, stylesheet.codeText)!;
|
||||
child.fillStyles(stylesheet, style);
|
||||
}
|
||||
|
||||
@override
|
||||
TextNodeLayoutBuilder get layoutBuilder => child.layoutBuilder;
|
||||
}
|
||||
@ -20,6 +20,7 @@ class DocumentStyle extends FlameTextStyle {
|
||||
InlineTextStyle? text,
|
||||
InlineTextStyle? boldText,
|
||||
InlineTextStyle? italicText,
|
||||
InlineTextStyle? codeText,
|
||||
BlockStyle? paragraph,
|
||||
BlockStyle? header1,
|
||||
BlockStyle? header2,
|
||||
@ -31,6 +32,7 @@ class DocumentStyle extends FlameTextStyle {
|
||||
_boldText = FlameTextStyle.merge(BoldTextNode.defaultStyle, boldText),
|
||||
_italicText =
|
||||
FlameTextStyle.merge(ItalicTextNode.defaultStyle, italicText),
|
||||
_codeText = FlameTextStyle.merge(CodeTextNode.defaultStyle, codeText),
|
||||
_paragraph =
|
||||
FlameTextStyle.merge(ParagraphNode.defaultStyle, paragraph),
|
||||
_header1 = FlameTextStyle.merge(HeaderNode.defaultStyleH1, header1),
|
||||
@ -43,6 +45,7 @@ class DocumentStyle extends FlameTextStyle {
|
||||
final InlineTextStyle? _text;
|
||||
final InlineTextStyle? _boldText;
|
||||
final InlineTextStyle? _italicText;
|
||||
final InlineTextStyle? _codeText;
|
||||
final BlockStyle? _paragraph;
|
||||
final BlockStyle? _header1;
|
||||
final BlockStyle? _header2;
|
||||
@ -94,6 +97,7 @@ class DocumentStyle extends FlameTextStyle {
|
||||
InlineTextStyle get text => _text!;
|
||||
InlineTextStyle get boldText => _boldText!;
|
||||
InlineTextStyle get italicText => _italicText!;
|
||||
InlineTextStyle get codeText => _codeText!;
|
||||
|
||||
/// Style for [ParagraphNode]s.
|
||||
BlockStyle get paragraph => _paragraph!;
|
||||
@ -117,6 +121,7 @@ class DocumentStyle extends FlameTextStyle {
|
||||
text: FlameTextStyle.merge(_text, other.text),
|
||||
boldText: FlameTextStyle.merge(_boldText, other.boldText),
|
||||
italicText: FlameTextStyle.merge(_italicText, other.italicText),
|
||||
codeText: FlameTextStyle.merge(_codeText, other.codeText),
|
||||
background: merge(background, other.background) as BackgroundStyle?,
|
||||
paragraph: merge(paragraph, other.paragraph) as BlockStyle?,
|
||||
header1: merge(header1, other.header1) as BlockStyle?,
|
||||
|
||||
@ -14,6 +14,7 @@ export 'src/text/elements/text_painter_text_element.dart'
|
||||
show TextPainterTextElement;
|
||||
export 'src/text/nodes/block_node.dart' show BlockNode;
|
||||
export 'src/text/nodes/bold_text_node.dart' show BoldTextNode;
|
||||
export 'src/text/nodes/code_text_node.dart' show CodeTextNode;
|
||||
export 'src/text/nodes/column_node.dart' show ColumnNode;
|
||||
export 'src/text/nodes/document_root.dart' show DocumentRoot;
|
||||
export 'src/text/nodes/group_text_node.dart' show GroupTextNode;
|
||||
|
||||
@ -55,6 +55,7 @@ class FlameMarkdown {
|
||||
'p' => ParagraphNode(child),
|
||||
'em' || 'i' => ItalicTextNode(child),
|
||||
'strong' || 'b' => BoldTextNode(child),
|
||||
'code' => CodeTextNode(child),
|
||||
_ => throw Exception('Unknown element tag: ${element.tag}'),
|
||||
} as TextNode;
|
||||
}
|
||||
|
||||
@ -29,6 +29,19 @@ void main() {
|
||||
]);
|
||||
});
|
||||
|
||||
test('inline code block', () {
|
||||
final doc = FlameMarkdown.toDocument('Flame: `var game = FlameGame();`');
|
||||
|
||||
_expectDocument(doc, [
|
||||
(node) => _expectParagraph(node, (p) {
|
||||
_expectGroup(p, [
|
||||
(node) => _expectPlain(node, 'Flame: '),
|
||||
(node) => _expectCode(node, 'var game = FlameGame();'),
|
||||
]);
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
test('all header levels', () {
|
||||
final doc = FlameMarkdown.toDocument(
|
||||
'# h1\n'
|
||||
@ -107,6 +120,13 @@ void _expectPlain(InlineTextNode node, String text) {
|
||||
expect(span.text, text);
|
||||
}
|
||||
|
||||
void _expectCode(InlineTextNode node, String text) {
|
||||
expect(node, isA<CodeTextNode>());
|
||||
final content = (node as CodeTextNode).child;
|
||||
expect(content, isA<PlainTextNode>());
|
||||
expect((content as PlainTextNode).text, text);
|
||||
}
|
||||
|
||||
void _expectParagraph(
|
||||
BlockNode node,
|
||||
void Function(InlineTextNode) expectChild,
|
||||
|
||||
Reference in New Issue
Block a user