Toggle navigation
Toggle navigation
This project
Loading...
Sign in
flutter_package
/
gpt_markdown
Go to a project
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
saminsohag
2025-02-15 10:51:24 +0600
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
a05f9cc54dbd3e009657ce9ce5a57851708f9a9c
a05f9cc5
1 parent
8bf9b7ed
dart formate
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
496 additions
and
452 deletions
CHANGELOG.md
lib/custom_widgets/code_field.dart
lib/custom_widgets/custom_divider.dart
lib/custom_widgets/custom_error_image.dart
lib/custom_widgets/custom_rb_cb.dart
lib/custom_widgets/link_button.dart
lib/custom_widgets/markdow_config.dart
lib/custom_widgets/selectable_adapter.dart
lib/custom_widgets/unordered_ordered_list.dart
lib/gpt_markdown.dart
lib/markdown_component.dart
lib/md_widget.dart
lib/theme.dart
pubspec.yaml
CHANGELOG.md
View file @
a05f9cc
## 1.0.11
*
dart format.
## 1.0.10
*
pubspec flutter version updated.
...
...
lib/custom_widgets/code_field.dart
View file @
a05f9cc
...
...
@@ -16,30 +16,29 @@ class _CodeFieldState extends State<CodeField> {
Widget
build
(
BuildContext
context
)
{
return
Material
(
color:
Theme
.
of
(
context
).
colorScheme
.
onInverseSurface
,
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
8
),
),
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
8
)),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
children:
[
Row
(
children:
[
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16.0
,
vertical:
8
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16.0
,
vertical:
8
,
),
child:
Text
(
widget
.
name
),
),
const
Spacer
(),
TextButton
.
icon
(
style:
TextButton
.
styleFrom
(
foregroundColor:
Theme
.
of
(
context
).
colorScheme
.
onSurface
,
textStyle:
const
TextStyle
(
fontWeight:
FontWeight
.
normal
,
),
textStyle:
const
TextStyle
(
fontWeight:
FontWeight
.
normal
),
),
onPressed:
()
async
{
await
Clipboard
.
setData
(
ClipboardData
(
text:
widget
.
codes
))
.
then
((
value
)
{
await
Clipboard
.
setData
(
ClipboardData
(
text:
widget
.
codes
),
).
then
((
value
)
{
setState
(()
{
_copied
=
true
;
});
...
...
@@ -57,15 +56,11 @@ class _CodeFieldState extends State<CodeField> {
),
],
),
const
Divider
(
height:
1
,
),
const
Divider
(
height:
1
),
SingleChildScrollView
(
scrollDirection:
Axis
.
horizontal
,
padding:
const
EdgeInsets
.
all
(
16
),
child:
Text
(
widget
.
codes
,
),
child:
Text
(
widget
.
codes
),
),
],
),
...
...
lib/custom_widgets/custom_divider.dart
View file @
a05f9cc
...
...
@@ -16,7 +16,9 @@ class CustomDivider extends LeafRenderObjectWidget {
@override
void
updateRenderObject
(
BuildContext
context
,
covariant
RenderDivider
renderObject
)
{
BuildContext
context
,
covariant
RenderDivider
renderObject
,
)
{
renderObject
.
color
=
color
??
Theme
.
of
(
context
).
colorScheme
.
outline
;
renderObject
.
height
=
height
??
2
;
renderObject
.
width
=
MediaQuery
.
sizeOf
(
context
).
width
;
...
...
@@ -25,9 +27,9 @@ class CustomDivider extends LeafRenderObjectWidget {
class
RenderDivider
extends
RenderBox
{
RenderDivider
(
Color
color
,
double
width
,
double
height
)
:
_color
=
color
,
_height
=
height
,
_width
=
width
;
:
_color
=
color
,
_height
=
height
,
_width
=
width
;
Color
_color
;
double
_height
;
double
_width
;
...
...
@@ -57,9 +59,10 @@ class RenderDivider extends RenderBox {
@override
Size
computeDryLayout
(
BoxConstraints
constraints
)
{
return
BoxConstraints
.
tightFor
(
width:
null
,
height:
_height
)
.
enforce
(
constraints
)
.
smallest
;
return
BoxConstraints
.
tightFor
(
width:
null
,
height:
_height
,
).
enforce
(
constraints
).
smallest
;
}
@override
...
...
@@ -69,7 +72,9 @@ class RenderDivider extends RenderBox {
@override
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
context
.
canvas
.
drawRect
(
offset
&
Size
(
Rect
.
largest
.
size
.
width
,
_height
),
Paint
()..
color
=
_color
);
context
.
canvas
.
drawRect
(
offset
&
Size
(
Rect
.
largest
.
size
.
width
,
_height
),
Paint
()..
color
=
_color
,
);
}
}
...
...
lib/custom_widgets/custom_error_image.dart
View file @
a05f9cc
...
...
@@ -25,8 +25,11 @@ class CustomImageError extends LeafRenderObjectWidget {
@override
void
updateRenderObject
(
BuildContext
context
,
covariant
RenderCustomImageError
renderObject
)
{
renderObject
.
_backgroundColor
=
backgroundColor
??
BuildContext
context
,
covariant
RenderCustomImageError
renderObject
,
)
{
renderObject
.
_backgroundColor
=
backgroundColor
??
Theme
.
of
(
context
).
colorScheme
.
surfaceContainerHighest
;
renderObject
.
_iconColor
=
iconColor
??
Theme
.
of
(
context
).
colorScheme
.
onSurfaceVariant
;
...
...
@@ -37,7 +40,10 @@ class CustomImageError extends LeafRenderObjectWidget {
class
RenderCustomImageError
extends
RenderProxyBox
{
RenderCustomImageError
(
this
.
_iconColor
,
this
.
_backgroundColor
,
this
.
_outlineColor
);
this
.
_iconColor
,
this
.
_backgroundColor
,
this
.
_outlineColor
,
);
Color
_iconColor
;
Color
_outlineColor
;
Color
_backgroundColor
;
...
...
@@ -68,29 +74,29 @@ class RenderCustomImageError extends RenderProxyBox {
@override
void
performLayout
()
{
if
(
constraints
.
hasBoundedHeight
&&
constraints
.
hasBoundedWidth
)
{
size
=
constraints
.
constrain
(
Size
(
size
=
constraints
.
constrain
(
Size
(
min
(
constraints
.
maxWidth
,
constraints
.
maxHeight
),
min
(
constraints
.
maxHeight
,
constraints
.
maxWidth
)));
min
(
constraints
.
maxHeight
,
constraints
.
maxWidth
),
),
);
return
;
}
if
(
constraints
.
hasBoundedHeight
||
constraints
.
hasBoundedWidth
)
{
size
=
constraints
.
constrain
(
Size
(
min
(
constraints
.
maxHeight
,
constraints
.
maxWidth
),
min
(
constraints
.
maxHeight
,
constraints
.
maxWidth
),
));
size
=
constraints
.
constrain
(
Size
(
min
(
constraints
.
maxHeight
,
constraints
.
maxWidth
),
min
(
constraints
.
maxHeight
,
constraints
.
maxWidth
),
),
);
return
;
}
size
=
constraints
.
constrain
(
const
Size
(
80
,
80
),
);
size
=
constraints
.
constrain
(
const
Size
(
80
,
80
));
}
@override
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
context
.
canvas
.
drawRect
(
offset
&
size
,
Paint
()..
color
=
_backgroundColor
,
);
context
.
canvas
.
drawRect
(
offset
&
size
,
Paint
()..
color
=
_backgroundColor
);
context
.
canvas
.
drawRect
(
offset
&
size
,
Paint
()
...
...
@@ -102,16 +108,19 @@ class RenderCustomImageError extends RenderProxyBox {
textPainter
.
text
=
TextSpan
(
text:
String
.
fromCharCode
(
icon
.
codePoint
),
style:
TextStyle
(
fontSize:
min
(
min
(
size
.
width
,
size
.
height
),
35
),
fontFamily:
icon
.
fontFamily
,
color:
_iconColor
),
fontSize:
min
(
min
(
size
.
width
,
size
.
height
),
35
),
fontFamily:
icon
.
fontFamily
,
color:
_iconColor
,
),
);
textPainter
.
layout
();
textPainter
.
paint
(
context
.
canvas
,
offset
+
Offset
(
size
.
width
/
2
-
textPainter
.
size
.
width
/
2
,
size
.
height
/
2
-
textPainter
.
size
.
height
/
2
),
Offset
(
size
.
width
/
2
-
textPainter
.
size
.
width
/
2
,
size
.
height
/
2
-
textPainter
.
size
.
height
/
2
,
),
);
}
}
...
...
@@ -141,8 +150,11 @@ class CustomImageLoading extends LeafRenderObjectWidget {
@override
void
updateRenderObject
(
BuildContext
context
,
covariant
RenderCustomImageLoading
renderObject
)
{
renderObject
.
_backgroundColor
=
backgroundColor
??
BuildContext
context
,
covariant
RenderCustomImageLoading
renderObject
,
)
{
renderObject
.
_backgroundColor
=
backgroundColor
??
Theme
.
of
(
context
).
colorScheme
.
surfaceContainerHighest
;
renderObject
.
_iconColor
=
iconColor
??
Theme
.
of
(
context
).
colorScheme
.
onSurfaceVariant
;
...
...
@@ -153,8 +165,12 @@ class CustomImageLoading extends LeafRenderObjectWidget {
}
class
RenderCustomImageLoading
extends
RenderProxyBox
{
RenderCustomImageLoading
(
this
.
_iconColor
,
this
.
_backgroundColor
,
this
.
_outlineColor
,
this
.
_progress
);
RenderCustomImageLoading
(
this
.
_iconColor
,
this
.
_backgroundColor
,
this
.
_outlineColor
,
this
.
_progress
,
);
Color
_iconColor
;
Color
_outlineColor
;
Color
_backgroundColor
;
...
...
@@ -194,29 +210,29 @@ class RenderCustomImageLoading extends RenderProxyBox {
@override
void
performLayout
()
{
if
(
constraints
.
hasBoundedHeight
&&
constraints
.
hasBoundedWidth
)
{
size
=
constraints
.
constrain
(
Size
(
size
=
constraints
.
constrain
(
Size
(
min
(
constraints
.
maxWidth
,
constraints
.
maxHeight
),
min
(
constraints
.
maxHeight
,
constraints
.
maxWidth
)));
min
(
constraints
.
maxHeight
,
constraints
.
maxWidth
),
),
);
return
;
}
if
(
constraints
.
hasBoundedHeight
||
constraints
.
hasBoundedWidth
)
{
size
=
constraints
.
constrain
(
Size
(
min
(
constraints
.
maxHeight
,
constraints
.
maxWidth
),
min
(
constraints
.
maxHeight
,
constraints
.
maxWidth
),
));
size
=
constraints
.
constrain
(
Size
(
min
(
constraints
.
maxHeight
,
constraints
.
maxWidth
),
min
(
constraints
.
maxHeight
,
constraints
.
maxWidth
),
),
);
return
;
}
size
=
constraints
.
constrain
(
const
Size
(
80
,
80
),
);
size
=
constraints
.
constrain
(
const
Size
(
80
,
80
));
}
@override
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
context
.
canvas
.
drawRect
(
offset
&
size
,
Paint
()..
color
=
_backgroundColor
,
);
context
.
canvas
.
drawRect
(
offset
&
size
,
Paint
()..
color
=
_backgroundColor
);
context
.
canvas
.
drawRect
(
offset
&
size
,
Paint
()
...
...
@@ -228,19 +244,23 @@ class RenderCustomImageLoading extends RenderProxyBox {
textPainter
.
text
=
TextSpan
(
text:
String
.
fromCharCode
(
icon
.
codePoint
),
style:
TextStyle
(
fontSize:
min
(
min
(
size
.
width
,
size
.
height
),
35
),
fontFamily:
icon
.
fontFamily
,
color:
_iconColor
),
fontSize:
min
(
min
(
size
.
width
,
size
.
height
),
35
),
fontFamily:
icon
.
fontFamily
,
color:
_iconColor
,
),
);
textPainter
.
layout
();
context
.
canvas
.
drawRect
(
(
offset
+
Offset
(
0
,
size
.
height
-
5
))
&
Size
(
size
.
width
*
_progress
,
5
),
Paint
()..
color
=
_iconColor
);
(
offset
+
Offset
(
0
,
size
.
height
-
5
))
&
Size
(
size
.
width
*
_progress
,
5
),
Paint
()..
color
=
_iconColor
,
);
textPainter
.
paint
(
context
.
canvas
,
offset
+
Offset
(
size
.
width
/
2
-
textPainter
.
size
.
width
/
2
,
size
.
height
/
2
-
textPainter
.
size
.
height
/
2
),
Offset
(
size
.
width
/
2
-
textPainter
.
size
.
width
/
2
,
size
.
height
/
2
-
textPainter
.
size
.
height
/
2
,
),
);
}
}
...
...
lib/custom_widgets/custom_rb_cb.dart
View file @
a05f9cc
...
...
@@ -25,8 +25,10 @@ class CustomRb extends StatelessWidget {
WidgetSpan
(
alignment:
PlaceholderAlignment
.
middle
,
child:
Padding
(
padding:
EdgeInsetsDirectional
.
only
(
start:
spacing
,
end:
spacing
),
padding:
EdgeInsetsDirectional
.
only
(
start:
spacing
,
end:
spacing
,
),
child:
Radio
(
value:
value
,
groupValue:
true
,
...
...
@@ -36,9 +38,7 @@ class CustomRb extends StatelessWidget {
),
),
),
Expanded
(
child:
child
,
)
Expanded
(
child:
child
),
],
),
);
...
...
@@ -70,15 +70,15 @@ class CustomCb extends StatelessWidget {
WidgetSpan
(
alignment:
PlaceholderAlignment
.
middle
,
child:
Padding
(
padding:
EdgeInsetsDirectional
.
only
(
start:
spacing
,
end:
spacing
),
padding:
EdgeInsetsDirectional
.
only
(
start:
spacing
,
end:
spacing
,
),
child:
Checkbox
(
value:
value
,
onChanged:
(
value
)
{}),
),
),
),
Expanded
(
child:
child
,
)
Expanded
(
child:
child
),
],
),
);
...
...
lib/custom_widgets/link_button.dart
View file @
a05f9cc
...
...
@@ -11,15 +11,16 @@ class LinkButton extends StatefulWidget {
final
Color
color
;
final
Color
hoverColor
;
const
LinkButton
(
{
super
.
key
,
required
this
.
text
,
required
this
.
config
,
required
this
.
color
,
required
this
.
hoverColor
,
this
.
onPressed
,
this
.
textStyle
,
this
.
url
});
const
LinkButton
({
super
.
key
,
required
this
.
text
,
required
this
.
config
,
required
this
.
color
,
required
this
.
hoverColor
,
this
.
onPressed
,
this
.
textStyle
,
this
.
url
,
});
@override
State
<
LinkButton
>
createState
()
=>
_LinkButtonState
();
...
...
@@ -44,12 +45,7 @@ class _LinkButtonState extends State<LinkButton> {
onTapUp:
(
_
)
=>
_handlePress
(
false
),
onTapCancel:
()
=>
_handlePress
(
false
),
onTap:
widget
.
onPressed
,
child:
widget
.
config
.
getRich
(
TextSpan
(
text:
widget
.
text
,
style:
style
,
),
),
child:
widget
.
config
.
getRich
(
TextSpan
(
text:
widget
.
text
,
style:
style
)),
),
);
}
...
...
lib/custom_widgets/markdow_config.dart
View file @
a05f9cc
...
...
@@ -24,21 +24,37 @@ class GptMarkdownConfig {
final
void
Function
(
String
url
,
String
title
)?
onLinkTab
;
final
String
Function
(
String
tex
)?
latexWorkaround
;
final
Widget
Function
(
BuildContext
context
,
String
tex
,
TextStyle
textStyle
,
bool
inline
)?
latexBuilder
;
BuildContext
context
,
String
tex
,
TextStyle
textStyle
,
bool
inline
,
)?
latexBuilder
;
final
Widget
Function
(
BuildContext
context
,
String
content
,
TextStyle
textStyle
)?
sourceTagBuilder
;
BuildContext
context
,
String
content
,
TextStyle
textStyle
,
)?
sourceTagBuilder
;
final
bool
followLinkColor
;
final
Widget
Function
(
BuildContext
context
,
String
name
,
String
code
,
bool
closed
)?
codeBuilder
;
BuildContext
context
,
String
name
,
String
code
,
bool
closed
,
)?
codeBuilder
;
final
int
?
maxLines
;
final
TextOverflow
?
overflow
;
final
Widget
Function
(
BuildContext
context
,
String
text
,
TextStyle
style
)?
highlightBuilder
;
highlightBuilder
;
final
Widget
Function
(
BuildContext
context
,
String
text
,
String
url
,
TextStyle
style
)?
linkBuilder
;
BuildContext
context
,
String
text
,
String
url
,
TextStyle
style
,
)?
linkBuilder
;
GptMarkdownConfig
copyWith
({
TextStyle
?
style
,
...
...
@@ -48,22 +64,37 @@ class GptMarkdownConfig {
final
TextScaler
?
textScaler
,
final
String
Function
(
String
tex
)?
latexWorkaround
,
final
Widget
Function
(
BuildContext
context
,
String
tex
,
TextStyle
textStyle
,
bool
inline
)?
latexBuilder
,
BuildContext
context
,
String
tex
,
TextStyle
textStyle
,
bool
inline
,
)?
latexBuilder
,
final
Widget
Function
(
BuildContext
context
,
String
content
,
TextStyle
textStyle
)?
sourceTagBuilder
,
BuildContext
context
,
String
content
,
TextStyle
textStyle
,
)?
sourceTagBuilder
,
bool
?
followLinkColor
,
final
Widget
Function
(
BuildContext
context
,
String
name
,
String
code
,
bool
closed
)?
codeBuilder
,
BuildContext
context
,
String
name
,
String
code
,
bool
closed
,
)?
codeBuilder
,
final
int
?
maxLines
,
final
TextOverflow
?
overflow
,
final
Widget
Function
(
BuildContext
context
,
String
text
,
TextStyle
style
)?
highlightBuilder
,
highlightBuilder
,
final
Widget
Function
(
BuildContext
context
,
String
text
,
String
url
,
TextStyle
style
)?
linkBuilder
,
BuildContext
context
,
String
text
,
String
url
,
TextStyle
style
,
)?
linkBuilder
,
})
{
return
GptMarkdownConfig
(
style:
style
??
this
.
style
,
...
...
lib/custom_widgets/selectable_adapter.dart
View file @
a05f9cc
...
...
@@ -2,8 +2,11 @@ import 'package:flutter/material.dart';
import
'package:flutter/rendering.dart'
;
class
SelectableAdapter
extends
StatelessWidget
{
const
SelectableAdapter
(
{
super
.
key
,
required
this
.
child
,
required
this
.
selectedText
});
const
SelectableAdapter
({
super
.
key
,
required
this
.
child
,
required
this
.
selectedText
,
});
final
Widget
child
;
final
String
selectedText
;
...
...
@@ -17,31 +20,37 @@ class SelectableAdapter extends StatelessWidget {
return
MouseRegion
(
cursor:
SystemMouseCursors
.
text
,
child:
_SelectableAdapter
(
registrar:
registrar
,
selectedText:
selectedText
,
child:
child
),
registrar:
registrar
,
selectedText:
selectedText
,
child:
child
,
),
);
}
}
class
_SelectableAdapter
extends
SingleChildRenderObjectWidget
{
const
_SelectableAdapter
(
{
required
this
.
registrar
,
required
Widget
child
,
required
this
.
selectedText
})
:
super
(
child:
child
);
const
_SelectableAdapter
({
required
this
.
registrar
,
required
Widget
child
,
required
this
.
selectedText
,
})
:
super
(
child:
child
);
final
SelectionRegistrar
registrar
;
final
String
selectedText
;
@override
_RenderSelectableAdapter
createRenderObject
(
BuildContext
context
)
{
return
_RenderSelectableAdapter
(
DefaultSelectionStyle
.
of
(
context
).
selectionColor
!,
registrar
,
selectedText
);
DefaultSelectionStyle
.
of
(
context
).
selectionColor
!,
registrar
,
selectedText
,
);
}
@override
void
updateRenderObject
(
BuildContext
context
,
_RenderSelectableAdapter
renderObject
)
{
BuildContext
context
,
_RenderSelectableAdapter
renderObject
,
)
{
renderObject
..
selectionColor
=
DefaultSelectionStyle
.
of
(
context
).
selectionColor
!
..
registrar
=
registrar
;
...
...
@@ -51,9 +60,11 @@ class _SelectableAdapter extends SingleChildRenderObjectWidget {
class
_RenderSelectableAdapter
extends
RenderProxyBox
with
Selectable
,
SelectionRegistrant
{
_RenderSelectableAdapter
(
Color
selectionColor
,
SelectionRegistrar
registrar
,
this
.
selectedText
)
:
_selectionColor
=
selectionColor
,
_geometry
=
ValueNotifier
<
SelectionGeometry
>(
_noSelection
)
{
Color
selectionColor
,
SelectionRegistrar
registrar
,
this
.
selectedText
,
)
:
_selectionColor
=
selectionColor
,
_geometry
=
ValueNotifier
<
SelectionGeometry
>(
_noSelection
)
{
this
.
registrar
=
registrar
;
_geometry
.
addListener
(
markNeedsPaint
);
}
...
...
@@ -152,13 +163,20 @@ class _RenderSelectableAdapter extends RenderProxyBox
switch
(
event
.
type
)
{
case
SelectionEventType
.
startEdgeUpdate
:
case
SelectionEventType
.
endEdgeUpdate
:
final
Rect
renderObjectRect
=
Rect
.
fromLTWH
(
0
,
0
,
size
.
width
,
size
.
height
);
final
Rect
renderObjectRect
=
Rect
.
fromLTWH
(
0
,
0
,
size
.
width
,
size
.
height
,
);
// Normalize offset in case it is out side of the rect.
final
Offset
point
=
globalToLocal
((
event
as
SelectionEdgeUpdateEvent
).
globalPosition
);
final
Offset
adjustedPoint
=
SelectionUtils
.
adjustDragOffset
(
renderObjectRect
,
point
);
final
Offset
point
=
globalToLocal
(
(
event
as
SelectionEdgeUpdateEvent
).
globalPosition
,
);
final
Offset
adjustedPoint
=
SelectionUtils
.
adjustDragOffset
(
renderObjectRect
,
point
,
);
if
(
event
.
type
==
SelectionEventType
.
startEdgeUpdate
)
{
_start
=
adjustedPoint
;
}
else
{
...
...
@@ -189,16 +207,18 @@ class _RenderSelectableAdapter extends RenderProxyBox
extendSelectionEvent
.
forward
?
Offset
.
infinite
:
Offset
.
zero
;
if
(
extendSelectionEvent
.
isEnd
)
{
if
(
newOffset
==
_end
)
{
result
=
extendSelectionEvent
.
forward
?
SelectionResult
.
next
:
SelectionResult
.
previous
;
result
=
extendSelectionEvent
.
forward
?
SelectionResult
.
next
:
SelectionResult
.
previous
;
}
_end
=
newOffset
;
}
else
{
if
(
newOffset
==
_start
)
{
result
=
extendSelectionEvent
.
forward
?
SelectionResult
.
next
:
SelectionResult
.
previous
;
result
=
extendSelectionEvent
.
forward
?
SelectionResult
.
next
:
SelectionResult
.
previous
;
}
_start
=
newOffset
;
}
...
...
@@ -296,18 +316,22 @@ class _RenderSelectableAdapter extends RenderProxyBox
return
;
}
// Draw the selection highlight.
final
Paint
selectionPaint
=
Paint
()
..
style
=
PaintingStyle
.
fill
..
color
=
_selectionColor
;
context
.
canvas
.
drawRect
(
_getSelectionHighlightRect
().
shift
(
offset
),
selectionPaint
);
final
Paint
selectionPaint
=
Paint
()
..
style
=
PaintingStyle
.
fill
..
color
=
_selectionColor
;
context
.
canvas
.
drawRect
(
_getSelectionHighlightRect
().
shift
(
offset
),
selectionPaint
,
);
// Push the layer links if any.
if
(
_startHandle
!=
null
)
{
context
.
pushLayer
(
LeaderLayer
(
link:
_startHandle
!,
offset:
offset
+
value
.
startSelectionPoint
!.
localPosition
),
link:
_startHandle
!,
offset:
offset
+
value
.
startSelectionPoint
!.
localPosition
,
),
(
PaintingContext
context
,
Offset
offset
)
{},
Offset
.
zero
,
);
...
...
@@ -315,8 +339,9 @@ class _RenderSelectableAdapter extends RenderProxyBox
if
(
_endHandle
!=
null
)
{
context
.
pushLayer
(
LeaderLayer
(
link:
_endHandle
!,
offset:
offset
+
value
.
endSelectionPoint
!.
localPosition
),
link:
_endHandle
!,
offset:
offset
+
value
.
endSelectionPoint
!.
localPosition
,
),
(
PaintingContext
context
,
Offset
offset
)
{},
Offset
.
zero
,
);
...
...
lib/custom_widgets/unordered_ordered_list.dart
View file @
a05f9cc
...
...
@@ -26,16 +26,16 @@ class UnorderedListView extends StatelessWidget {
crossAxisAlignment:
CrossAxisAlignment
.
baseline
,
children:
[
if
(
bulletSize
==
0
)
SizedBox
(
width:
spacing
+
padding
,
)
SizedBox
(
width:
spacing
+
padding
)
else
Text
.
rich
(
WidgetSpan
(
alignment:
PlaceholderAlignment
.
middle
,
child:
Padding
(
padding:
EdgeInsetsDirectional
.
only
(
start:
padding
,
end:
spacing
),
padding:
EdgeInsetsDirectional
.
only
(
start:
padding
,
end:
spacing
,
),
child:
Container
(
width:
bulletSize
,
height:
bulletSize
,
...
...
@@ -47,9 +47,7 @@ class UnorderedListView extends StatelessWidget {
),
),
),
Expanded
(
child:
child
,
)
Expanded
(
child:
child
),
],
),
);
...
...
@@ -60,15 +58,15 @@ class OrderedListView extends StatelessWidget {
final
String
no
;
final
double
spacing
;
final
double
padding
;
const
OrderedListView
(
{
super
.
key
,
this
.
spacing
=
6
,
this
.
padding
=
6
,
TextStyle
?
style
,
required
this
.
child
,
this
.
textDirection
=
TextDirection
.
ltr
,
required
this
.
no
})
:
_style
=
style
;
const
OrderedListView
({
super
.
key
,
this
.
spacing
=
6
,
this
.
padding
=
6
,
TextStyle
?
style
,
required
this
.
child
,
this
.
textDirection
=
TextDirection
.
ltr
,
required
this
.
no
,
})
:
_style
=
style
;
final
TextStyle
?
_style
;
final
TextDirection
textDirection
;
final
Widget
child
;
...
...
@@ -83,16 +81,9 @@ class OrderedListView extends StatelessWidget {
children:
[
Padding
(
padding:
EdgeInsetsDirectional
.
only
(
start:
padding
,
end:
spacing
),
child:
Text
.
rich
(
TextSpan
(
text:
no
,
),
style:
_style
,
),
child:
Text
.
rich
(
TextSpan
(
text:
no
),
style:
_style
),
),
Expanded
(
child:
child
,
)
Expanded
(
child:
child
),
],
),
);
...
...
lib/gpt_markdown.dart
View file @
a05f9cc
...
...
@@ -48,44 +48,52 @@ class GptMarkdown extends StatelessWidget {
final
int
?
maxLines
;
final
TextOverflow
?
overflow
;
final
Widget
Function
(
BuildContext
context
,
String
tex
,
TextStyle
style
,
bool
inline
)?
latexBuilder
;
BuildContext
context
,
String
tex
,
TextStyle
style
,
bool
inline
,
)?
latexBuilder
;
final
bool
followLinkColor
;
final
Widget
Function
(
BuildContext
context
,
String
name
,
String
code
,
bool
closed
)?
codeBuilder
;
BuildContext
context
,
String
name
,
String
code
,
bool
closed
,
)?
codeBuilder
;
final
Widget
Function
(
BuildContext
,
String
,
TextStyle
)?
sourceTagBuilder
;
final
Widget
Function
(
BuildContext
context
,
String
text
,
TextStyle
style
)?
highlightBuilder
;
highlightBuilder
;
final
Widget
Function
(
BuildContext
context
,
String
text
,
String
url
,
TextStyle
style
)?
linkBuilder
;
BuildContext
context
,
String
text
,
String
url
,
TextStyle
style
,
)?
linkBuilder
;
String
_removeExtraLinesInsideBlockLatex
(
String
text
)
{
return
text
.
replaceAllMapped
(
RegExp
(
r"\\\[(.*?)\\\]"
,
multiLine:
true
,
dotAll:
true
,
),
(
match
)
{
String
content
=
match
[
0
]
??
""
;
return
content
.
replaceAllMapped
(
RegExp
(
r"\n[\n\ ]+"
),
(
match
)
=>
"
\n
"
);
});
RegExp
(
r"\\\[(.*?)\\\]"
,
multiLine:
true
,
dotAll:
true
),
(
match
)
{
String
content
=
match
[
0
]
??
""
;
return
content
.
replaceAllMapped
(
RegExp
(
r"\n[\n\ ]+"
),
(
match
)
=>
"
\n
"
);
},
);
}
@override
Widget
build
(
BuildContext
context
)
{
String
tex
=
data
.
trim
();
tex
=
tex
.
replaceAllMapped
(
RegExp
(
r"(?<!\\)\$\$(.*?)(?<!\\)\$\$"
,
dotAll:
true
,
),
(
match
)
=>
"
\\
[
${match[1] ?? ""}
\\
]"
);
RegExp
(
r"(?<!\\)\$\$(.*?)(?<!\\)\$\$"
,
dotAll:
true
),
(
match
)
=>
"
\\
[
${match[1] ?? ""}
\\
]"
,
);
if
(!
tex
.
contains
(
r"\("
))
{
tex
=
tex
.
replaceAllMapped
(
RegExp
(
r"(?<!\\)\$(.*?)(?<!\\)\$"
,
),
(
match
)
=>
"
\\
(
${match[1] ?? ""}
\\
)"
);
RegExp
(
r"(?<!\\)\$(.*?)(?<!\\)\$"
),
(
match
)
=>
"
\\
(
${match[1] ?? ""}
\\
)"
,
);
tex
=
tex
.
splitMapJoin
(
RegExp
(
r"\[.*?\]|\(.*?\)"
),
onNonMatch:
(
p0
)
{
...
...
@@ -95,24 +103,25 @@ class GptMarkdown extends StatelessWidget {
}
tex
=
_removeExtraLinesInsideBlockLatex
(
tex
);
return
ClipRRect
(
child:
MdWidget
(
tex
,
config:
GptMarkdownConfig
(
textDirection:
textDirection
,
style:
style
,
onLinkTab:
onLinkTab
,
textAlign:
textAlign
,
textScaler:
textScaler
,
followLinkColor:
followLinkColor
,
latexWorkaround:
latexWorkaround
,
latexBuilder:
latexBuilder
,
codeBuilder:
codeBuilder
,
maxLines:
maxLines
,
overflow:
overflow
,
sourceTagBuilder:
sourceTagBuilder
,
highlightBuilder:
highlightBuilder
,
linkBuilder:
linkBuilder
,
child:
MdWidget
(
tex
,
config:
GptMarkdownConfig
(
textDirection:
textDirection
,
style:
style
,
onLinkTab:
onLinkTab
,
textAlign:
textAlign
,
textScaler:
textScaler
,
followLinkColor:
followLinkColor
,
latexWorkaround:
latexWorkaround
,
latexBuilder:
latexBuilder
,
codeBuilder:
codeBuilder
,
maxLines:
maxLines
,
overflow:
overflow
,
sourceTagBuilder:
sourceTagBuilder
,
highlightBuilder:
highlightBuilder
,
linkBuilder:
linkBuilder
,
),
),
)
)
;
);
}
}
...
...
lib/markdown_component.dart
View file @
a05f9cc
...
...
@@ -3,27 +3,27 @@ part of 'gpt_markdown.dart';
/// Markdown components
abstract
class
MarkdownComponent
{
static
List
<
MarkdownComponent
>
get
components
=>
[
CodeBlockMd
(),
NewLines
(),
IndentMd
(),
ImageMd
(),
TableMd
(),
HTag
(),
UnOrderedList
(),
OrderedList
(),
RadioButtonMd
(),
CheckBoxMd
(),
HrLine
(),
LatexMath
(),
LatexMathMultiLine
(),
ImageMd
(),
HighlightedText
(),
StrikeMd
(),
BoldMd
(),
ItalicMd
(),
ATagMd
(),
SourceTag
(),
];
CodeBlockMd
(),
NewLines
(),
IndentMd
(),
ImageMd
(),
TableMd
(),
HTag
(),
UnOrderedList
(),
OrderedList
(),
RadioButtonMd
(),
CheckBoxMd
(),
HrLine
(),
LatexMath
(),
LatexMathMultiLine
(),
ImageMd
(),
HighlightedText
(),
StrikeMd
(),
BoldMd
(),
ItalicMd
(),
ATagMd
(),
SourceTag
(),
];
/// Generate widget for markdown widget
static
List
<
InlineSpan
>
generate
(
...
...
@@ -46,11 +46,7 @@ abstract class MarkdownComponent {
for
(
var
each
in
components
)
{
if
(
each
.
exp
.
hasMatch
(
element
))
{
if
(
each
.
inline
)
{
spans
.
add
(
each
.
span
(
context
,
element
,
config
,
));
spans
.
add
(
each
.
span
(
context
,
element
,
config
));
}
else
{
spans
.
addAll
([
TextSpan
(
...
...
@@ -61,11 +57,7 @@ abstract class MarkdownComponent {
color:
config
.
style
?.
color
,
),
),
each
.
span
(
context
,
element
,
config
,
),
each
.
span
(
context
,
element
,
config
),
TextSpan
(
text:
"
\n
"
,
style:
TextStyle
(
...
...
@@ -82,12 +74,7 @@ abstract class MarkdownComponent {
return
""
;
},
onNonMatch:
(
p0
)
{
spans
.
add
(
TextSpan
(
text:
p0
,
style:
config
.
style
,
),
);
spans
.
add
(
TextSpan
(
text:
p0
,
style:
config
.
style
));
return
""
;
},
);
...
...
@@ -124,11 +111,7 @@ abstract class BlockMd extends MarkdownComponent {
bool
get
inline
=>
false
;
@override
RegExp
get
exp
=>
RegExp
(
r'^\ *?'
+
expString
,
dotAll:
true
,
multiLine:
true
,
);
RegExp
get
exp
=>
RegExp
(
r'^\ *?'
+
expString
,
dotAll:
true
,
multiLine:
true
);
String
get
expString
;
...
...
@@ -141,22 +124,12 @@ abstract class BlockMd extends MarkdownComponent {
var
matches
=
RegExp
(
r'^(?<spaces>\ \ +).*'
).
firstMatch
(
text
);
var
spaces
=
matches
?.
namedGroup
(
'spaces'
);
var
length
=
spaces
?.
length
??
0
;
var
child
=
build
(
context
,
text
,
config
,
);
var
child
=
build
(
context
,
text
,
config
);
length
=
min
(
length
,
4
);
if
(
length
>
0
)
{
child
=
UnorderedListView
(
spacing:
length
*
6.0
,
child:
child
,
);
child
=
UnorderedListView
(
spacing:
length
*
6.0
,
child:
child
);
}
return
WidgetSpan
(
child:
child
,
alignment:
PlaceholderAlignment
.
middle
,
);
return
WidgetSpan
(
child:
child
,
alignment:
PlaceholderAlignment
.
middle
);
}
Widget
build
(
...
...
@@ -186,10 +159,7 @@ class HTag extends BlockMd {
theme
.
h4
,
theme
.
h5
,
theme
.
h6
,
][
match
![
1
]!.
length
-
1
]
?.
copyWith
(
color:
config
.
style
?.
color
,
),
][
match
![
1
]!.
length
-
1
]?.
copyWith
(
color:
config
.
style
?.
color
),
);
return
config
.
getRich
(
TextSpan
(
...
...
@@ -207,7 +177,8 @@ class HTag extends BlockMd {
WidgetSpan
(
child:
CustomDivider
(
height:
theme
.
hrLineThickness
,
color:
config
.
style
?.
color
??
color:
config
.
style
?.
color
??
Theme
.
of
(
context
).
colorScheme
.
outline
,
),
),
...
...
@@ -229,10 +200,7 @@ class NewLines extends InlineMd {
)
{
return
TextSpan
(
text:
"
\n\n\n\n
"
,
style:
TextStyle
(
fontSize:
6
,
color:
config
.
style
?.
color
,
),
style:
TextStyle
(
fontSize:
6
,
color:
config
.
style
?.
color
),
);
}
}
...
...
@@ -272,10 +240,7 @@ class CheckBoxMd extends BlockMd {
return
CustomCb
(
value:
(
"
${match?[1]}
"
==
"x"
),
textDirection:
config
.
textDirection
,
child:
MdWidget
(
"
${match?[2]}
"
,
config:
config
,
),
child:
MdWidget
(
"
${match?[2]}
"
,
config:
config
),
);
}
}
...
...
@@ -296,10 +261,7 @@ class RadioButtonMd extends BlockMd {
return
CustomRb
(
value:
(
"
${match?[1]}
"
==
"x"
),
textDirection:
config
.
textDirection
,
child:
MdWidget
(
"
${match?[2]}
"
,
config:
config
,
),
child:
MdWidget
(
"
${match?[2]}
"
,
config:
config
),
);
}
}
...
...
@@ -310,8 +272,8 @@ class IndentMd extends InlineMd {
bool
get
inline
=>
false
;
@override
RegExp
get
exp
=>
// RegExp(r"(?<=\n\n)(\ +)(.+?)(?=\n\n)", dotAll: true, multiLine: true);
RegExp
(
r"^>([^\n]+)$"
,
dotAll:
true
,
multiLine:
true
);
// RegExp(r"(?<=\n\n)(\ +)(.+?)(?=\n\n)", dotAll: true, multiLine: true);
RegExp
(
r"^>([^\n]+)$"
,
dotAll:
true
,
multiLine:
true
);
@override
InlineSpan
span
(
...
...
@@ -324,11 +286,7 @@ class IndentMd extends InlineMd {
// data = data.replaceAll(RegExp(r'\n\ {' '$spaces' '}'), '\n').trim();
data
=
data
.
trim
();
var
child
=
TextSpan
(
children:
MarkdownComponent
.
generate
(
context
,
data
,
config
,
),
children:
MarkdownComponent
.
generate
(
context
,
data
,
config
),
);
return
TextSpan
(
children:
[
...
...
@@ -370,15 +328,13 @@ class UnOrderedList extends BlockMd {
(
config
.
style
?.
color
??
DefaultTextStyle
.
of
(
context
).
style
.
color
),
padding:
7
,
spacing:
10
,
bulletSize:
0.3
*
bulletSize:
0.3
*
(
config
.
style
?.
fontSize
??
DefaultTextStyle
.
of
(
context
).
style
.
fontSize
??
kDefaultFontSize
),
textDirection:
config
.
textDirection
,
child:
MdWidget
(
"
${match?[1]?.trim()}
"
,
config:
config
,
),
child:
MdWidget
(
"
${match?[1]?.trim()}
"
,
config:
config
),
);
}
}
...
...
@@ -398,12 +354,10 @@ class OrderedList extends BlockMd {
return
OrderedListView
(
no:
"
${match?[1]}
"
,
textDirection:
config
.
textDirection
,
style:
(
config
.
style
??
const
TextStyle
())
.
copyWith
(
fontWeight:
FontWeight
.
w100
),
child:
MdWidget
(
"
${match?[2]?.trim()}
"
,
config:
config
,
style:
(
config
.
style
??
const
TextStyle
()).
copyWith
(
fontWeight:
FontWeight
.
w100
,
),
child:
MdWidget
(
"
${match?[2]?.trim()}
"
,
config:
config
),
);
}
}
...
...
@@ -432,25 +386,25 @@ class HighlightedText extends InlineMd {
);
}
var
style
=
config
.
style
?.
copyWith
(
var
style
=
config
.
style
?.
copyWith
(
fontWeight:
FontWeight
.
bold
,
background:
Paint
()
..
color
=
GptMarkdownTheme
.
of
(
context
).
highlightColor
..
strokeCap
=
StrokeCap
.
round
..
strokeJoin
=
StrokeJoin
.
round
,
background:
Paint
()
..
color
=
GptMarkdownTheme
.
of
(
context
).
highlightColor
..
strokeCap
=
StrokeCap
.
round
..
strokeJoin
=
StrokeJoin
.
round
,
)
??
TextStyle
(
fontWeight:
FontWeight
.
bold
,
background:
Paint
()
..
color
=
GptMarkdownTheme
.
of
(
context
).
highlightColor
..
strokeCap
=
StrokeCap
.
round
..
strokeJoin
=
StrokeJoin
.
round
,
background:
Paint
()
..
color
=
GptMarkdownTheme
.
of
(
context
).
highlightColor
..
strokeCap
=
StrokeCap
.
round
..
strokeJoin
=
StrokeJoin
.
round
,
);
return
TextSpan
(
text:
highlightedText
,
style:
style
,
);
return
TextSpan
(
text:
highlightedText
,
style:
style
);
}
}
...
...
@@ -467,14 +421,12 @@ class BoldMd extends InlineMd {
)
{
var
match
=
exp
.
firstMatch
(
text
.
trim
());
var
conf
=
config
.
copyWith
(
style:
config
.
style
?.
copyWith
(
fontWeight:
FontWeight
.
bold
)
??
const
TextStyle
(
fontWeight:
FontWeight
.
bold
));
style:
config
.
style
?.
copyWith
(
fontWeight:
FontWeight
.
bold
)
??
const
TextStyle
(
fontWeight:
FontWeight
.
bold
),
);
return
TextSpan
(
children:
MarkdownComponent
.
generate
(
context
,
"
${match?[1]}
"
,
conf
,
),
children:
MarkdownComponent
.
generate
(
context
,
"
${match?[1]}
"
,
conf
),
style:
conf
.
style
,
);
}
...
...
@@ -492,19 +444,15 @@ class StrikeMd extends InlineMd {
)
{
var
match
=
exp
.
firstMatch
(
text
.
trim
());
var
conf
=
config
.
copyWith
(
style:
config
.
style
?.
copyWith
(
decoration:
TextDecoration
.
lineThrough
,
decorationColor:
config
.
style
?.
color
,
)
??
const
TextStyle
(
decoration:
TextDecoration
.
lineThrough
,
));
style:
config
.
style
?.
copyWith
(
decoration:
TextDecoration
.
lineThrough
,
decorationColor:
config
.
style
?.
color
,
)
??
const
TextStyle
(
decoration:
TextDecoration
.
lineThrough
),
);
return
TextSpan
(
children:
MarkdownComponent
.
generate
(
context
,
"
${match?[1]}
"
,
conf
,
),
children:
MarkdownComponent
.
generate
(
context
,
"
${match?[1]}
"
,
conf
),
style:
conf
.
style
,
);
}
...
...
@@ -513,9 +461,10 @@ class StrikeMd extends InlineMd {
/// Italic text component
class
ItalicMd
extends
InlineMd
{
@override
RegExp
get
exp
=>
RegExp
(
r"(?<!\*)\*(?<!\s)(.+?)(?<!\s)\*(?!\*)|\_(?<!\s)(.+?)(?<!\s)\_"
,
dotAll:
true
);
RegExp
get
exp
=>
RegExp
(
r"(?<!\*)\*(?<!\s)(.+?)(?<!\s)\*(?!\*)|\_(?<!\s)(.+?)(?<!\s)\_"
,
dotAll:
true
,
);
@override
InlineSpan
span
(
...
...
@@ -526,14 +475,12 @@ class ItalicMd extends InlineMd {
var
match
=
exp
.
firstMatch
(
text
.
trim
());
var
data
=
match
?[
1
]
??
match
?[
2
];
var
conf
=
config
.
copyWith
(
style:
(
config
.
style
??
const
TextStyle
())
.
copyWith
(
fontStyle:
FontStyle
.
italic
));
return
TextSpan
(
children:
MarkdownComponent
.
generate
(
context
,
"
$data
"
,
conf
,
style:
(
config
.
style
??
const
TextStyle
()).
copyWith
(
fontStyle:
FontStyle
.
italic
,
),
);
return
TextSpan
(
children:
MarkdownComponent
.
generate
(
context
,
"
$data
"
,
conf
),
style:
conf
.
style
,
);
}
...
...
@@ -555,7 +502,8 @@ class LatexMathMultiLine extends BlockMd {
String
mathText
=
p0
?[
1
]
??
p0
?[
2
]
??
""
;
var
workaround
=
config
.
latexWorkaround
??
(
String
tex
)
=>
tex
;
var
builder
=
config
.
latexBuilder
??
var
builder
=
config
.
latexBuilder
??
(
BuildContext
context
,
String
tex
,
TextStyle
textStyle
,
bool
inline
)
=>
SelectableAdapter
(
selectedText:
tex
,
...
...
@@ -564,14 +512,14 @@ class LatexMathMultiLine extends BlockMd {
textStyle:
textStyle
,
mathStyle:
MathStyle
.
display
,
textScaleFactor:
1
,
settings:
const
TexParserSettings
(
strict:
Strict
.
ignore
,
),
settings:
const
TexParserSettings
(
strict:
Strict
.
ignore
),
options:
MathOptions
(
sizeUnderTextStyle:
MathSize
.
large
,
color:
config
.
style
?.
color
??
color:
config
.
style
?.
color
??
Theme
.
of
(
context
).
colorScheme
.
onSurface
,
fontSize:
config
.
style
?.
fontSize
??
fontSize:
config
.
style
?.
fontSize
??
Theme
.
of
(
context
).
textTheme
.
bodyMedium
?.
fontSize
,
mathFontOptions:
FontOptions
(
fontFamily:
"Main"
,
...
...
@@ -590,15 +538,21 @@ class LatexMathMultiLine extends BlockMd {
workaround
(
mathText
),
textDirection:
config
.
textDirection
,
style:
textStyle
.
copyWith
(
color:
(!
kDebugMode
)
?
null
:
Theme
.
of
(
context
).
colorScheme
.
error
),
color:
(!
kDebugMode
)
?
null
:
Theme
.
of
(
context
).
colorScheme
.
error
,
),
);
},
),
);
return
builder
(
context
,
workaround
(
mathText
),
config
.
style
??
const
TextStyle
(),
false
);
return
builder
(
context
,
workaround
(
mathText
),
config
.
style
??
const
TextStyle
(),
false
,
);
}
}
...
...
@@ -606,12 +560,12 @@ class LatexMathMultiLine extends BlockMd {
class
LatexMath
extends
InlineMd
{
@override
RegExp
get
exp
=>
RegExp
(
[
r"\\\((.*?)\\\)"
,
// r"(?<!\\)\$((?:\\.|[^$])*?)\$(?!\\)",
].
join
(
"|"
),
dotAll:
true
,
);
[
r"\\\((.*?)\\\)"
,
// r"(?<!\\)\$((?:\\.|[^$])*?)\$(?!\\)",
].
join
(
"|"
),
dotAll:
true
,
);
@override
InlineSpan
span
(
...
...
@@ -623,7 +577,8 @@ class LatexMath extends InlineMd {
p0
?.
group
(
0
);
String
mathText
=
p0
?[
1
]?.
toString
()
??
""
;
var
workaround
=
config
.
latexWorkaround
??
(
String
tex
)
=>
tex
;
var
builder
=
config
.
latexBuilder
??
var
builder
=
config
.
latexBuilder
??
(
BuildContext
context
,
String
tex
,
TextStyle
textStyle
,
bool
inline
)
=>
SelectableAdapter
(
selectedText:
tex
,
...
...
@@ -632,14 +587,14 @@ class LatexMath extends InlineMd {
textStyle:
textStyle
,
mathStyle:
MathStyle
.
display
,
textScaleFactor:
1
,
settings:
const
TexParserSettings
(
strict:
Strict
.
ignore
,
),
settings:
const
TexParserSettings
(
strict:
Strict
.
ignore
),
options:
MathOptions
(
sizeUnderTextStyle:
MathSize
.
large
,
color:
config
.
style
?.
color
??
color:
config
.
style
?.
color
??
Theme
.
of
(
context
).
colorScheme
.
onSurface
,
fontSize:
config
.
style
?.
fontSize
??
fontSize:
config
.
style
?.
fontSize
??
Theme
.
of
(
context
).
textTheme
.
bodyMedium
?.
fontSize
,
mathFontOptions:
FontOptions
(
fontFamily:
"Main"
,
...
...
@@ -658,9 +613,11 @@ class LatexMath extends InlineMd {
workaround
(
mathText
),
textDirection:
config
.
textDirection
,
style:
textStyle
.
copyWith
(
color:
(!
kDebugMode
)
?
null
:
Theme
.
of
(
context
).
colorScheme
.
error
),
color:
(!
kDebugMode
)
?
null
:
Theme
.
of
(
context
).
colorScheme
.
error
,
),
);
},
),
...
...
@@ -668,8 +625,12 @@ class LatexMath extends InlineMd {
return
WidgetSpan
(
alignment:
PlaceholderAlignment
.
baseline
,
baseline:
TextBaseline
.
alphabetic
,
child:
builder
(
context
,
workaround
(
mathText
),
config
.
style
??
const
TextStyle
(),
true
),
child:
builder
(
context
,
workaround
(
mathText
),
config
.
style
??
const
TextStyle
(),
true
,
),
);
}
}
...
...
@@ -694,8 +655,12 @@ class SourceTag extends InlineMd {
alignment:
PlaceholderAlignment
.
middle
,
child:
Padding
(
padding:
const
EdgeInsets
.
all
(
2
),
child:
config
.
sourceTagBuilder
?.
call
(
context
,
content
,
const
TextStyle
())
??
child:
config
.
sourceTagBuilder
?.
call
(
context
,
content
,
const
TextStyle
(),
)
??
SizedBox
(
width:
20
,
height:
20
,
...
...
@@ -784,8 +749,9 @@ class ImageMd extends InlineMd {
double
?
height
;
double
?
width
;
if
(
match
?[
1
]
!=
null
)
{
var
size
=
RegExp
(
r"^([0-9]+)?x?([0-9]+)?"
)
.
firstMatch
(
match
![
1
].
toString
().
trim
());
var
size
=
RegExp
(
r"^([0-9]+)?x?([0-9]+)?"
,
).
firstMatch
(
match
![
1
].
toString
().
trim
());
width
=
double
.
tryParse
(
size
?[
1
]?.
toString
().
trim
()
??
'a'
);
height
=
double
.
tryParse
(
size
?[
2
]?.
toString
().
trim
()
??
'a'
);
}
...
...
@@ -795,19 +761,21 @@ class ImageMd extends InlineMd {
width:
width
,
height:
height
,
child:
Image
(
image:
NetworkImage
(
"
${match?[2]}
"
,
),
loadingBuilder:
(
BuildContext
context
,
Widget
child
,
ImageChunkEvent
?
loadingProgress
)
{
image:
NetworkImage
(
"
${match?[2]}
"
),
loadingBuilder:
(
BuildContext
context
,
Widget
child
,
ImageChunkEvent
?
loadingProgress
,
)
{
if
(
loadingProgress
==
null
)
{
return
child
;
}
return
CustomImageLoading
(
progress:
loadingProgress
.
expectedTotalBytes
!=
null
?
loadingProgress
.
cumulativeBytesLoaded
/
loadingProgress
.
expectedTotalBytes
!
:
1
,
progress:
loadingProgress
.
expectedTotalBytes
!=
null
?
loadingProgress
.
cumulativeBytesLoaded
/
loadingProgress
.
expectedTotalBytes
!
:
1
,
);
},
fit:
BoxFit
.
fill
,
...
...
@@ -831,16 +799,18 @@ class TableMd extends BlockMd {
String
text
,
final
GptMarkdownConfig
config
,
)
{
final
List
<
Map
<
int
,
String
>>
value
=
text
.
split
(
'
\n
'
)
.
map
<
Map
<
int
,
String
>>(
(
e
)
=>
e
.
split
(
'|'
)
.
where
((
element
)
=>
element
.
isNotEmpty
)
.
toList
()
.
asMap
(),
)
.
toList
();
final
List
<
Map
<
int
,
String
>>
value
=
text
.
split
(
'
\n
'
)
.
map
<
Map
<
int
,
String
>>(
(
e
)
=>
e
.
split
(
'|'
)
.
where
((
element
)
=>
element
.
isNotEmpty
)
.
toList
()
.
asMap
(),
)
.
toList
();
bool
heading
=
RegExp
(
r"^\|.*?\|\n\|-[-\\ |]*?-\|$"
,
multiLine:
true
,
...
...
@@ -868,45 +838,47 @@ class TableMd extends BlockMd {
width:
1
,
color:
Theme
.
of
(
context
).
colorScheme
.
onSurface
,
),
children:
value
.
asMap
()
.
entries
.
map
<
TableRow
>(
(
entry
)
=>
TableRow
(
decoration:
(
heading
)
?
BoxDecoration
(
color:
(
entry
.
key
==
0
)
?
Theme
.
of
(
context
)
.
colorScheme
.
surfaceContainerHighest
children:
value
.
asMap
()
.
entries
.
map
<
TableRow
>(
(
entry
)
=>
TableRow
(
decoration:
(
heading
)
?
BoxDecoration
(
color:
(
entry
.
key
==
0
)
?
Theme
.
of
(
context
,
).
colorScheme
.
surfaceContainerHighest
:
null
,
)
:
null
,
)
:
null
,
children:
List
.
generate
(
maxCol
,
(
index
)
{
var
e
=
entry
.
value
;
String
data
=
e
[
index
]
??
""
;
if
(
RegExp
(
r"^--+$"
).
hasMatch
(
data
.
trim
())
||
data
.
trim
().
isEmpty
)
{
return
const
SizedBox
();
}
return
Center
(
child:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8
,
vertical:
4
),
child:
MdWidget
(
(
e
[
index
]
??
""
).
trim
(),
config:
config
,
children:
List
.
generate
(
maxCol
,
(
index
)
{
var
e
=
entry
.
value
;
String
data
=
e
[
index
]
??
""
;
if
(
RegExp
(
r"^--+$"
).
hasMatch
(
data
.
trim
())
||
data
.
trim
().
isEmpty
)
{
return
const
SizedBox
();
}
return
Center
(
child:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8
,
vertical:
4
,
),
child:
MdWidget
(
(
e
[
index
]
??
""
).
trim
(),
config:
config
,
),
),
),
);
},
),
),
)
.
toList
(),
);
}),
),
)
.
toList
(),
),
),
);
...
...
lib/md_widget.dart
View file @
a05f9cc
...
...
@@ -2,11 +2,7 @@ part of 'gpt_markdown.dart';
/// It creates a markdown widget closed to each other.
class
MdWidget
extends
StatelessWidget
{
const
MdWidget
(
this
.
exp
,
{
super
.
key
,
required
this
.
config
,
});
const
MdWidget
(
this
.
exp
,
{
super
.
key
,
required
this
.
config
});
final
String
exp
;
final
GptMarkdownConfig
config
;
...
...
@@ -31,10 +27,7 @@ class MdWidget extends StatelessWidget {
),
);
return
config
.
getRich
(
TextSpan
(
children:
list
,
style:
config
.
style
?.
copyWith
(),
),
TextSpan
(
children:
list
,
style:
config
.
style
?.
copyWith
()),
);
}
}
...
...
lib/theme.dart
View file @
a05f9cc
...
...
@@ -39,8 +39,9 @@ class GptMarkdownThemeData extends ThemeExtension<GptMarkdownThemeData> {
displayMedium:
Typography
.
tall2021
.
displayMedium
?.
copyWith
(
inherit:
true
),
displaySmall:
Typography
.
tall2021
.
displaySmall
?.
copyWith
(
inherit:
true
),
headlineLarge:
Typography
.
tall2021
.
headlineLarge
?.
copyWith
(
inherit:
true
),
headlineMedium:
Typography
.
tall2021
.
headlineMedium
?.
copyWith
(
inherit:
true
),
headlineMedium:
Typography
.
tall2021
.
headlineMedium
?.
copyWith
(
inherit:
true
,
),
headlineSmall:
Typography
.
tall2021
.
headlineSmall
?.
copyWith
(
inherit:
true
),
titleLarge:
Typography
.
tall2021
.
titleLarge
?.
copyWith
(
inherit:
true
),
titleMedium:
Typography
.
tall2021
.
titleMedium
?.
copyWith
(
inherit:
true
),
...
...
@@ -52,9 +53,7 @@ class GptMarkdownThemeData extends ThemeExtension<GptMarkdownThemeData> {
labelMedium:
Typography
.
tall2021
.
labelMedium
?.
copyWith
(
inherit:
true
),
labelSmall:
Typography
.
tall2021
.
labelSmall
?.
copyWith
(
inherit:
true
),
);
themeData
=
themeData
.
copyWith
(
textTheme:
typography
,
);
themeData
=
themeData
.
copyWith
(
textTheme:
typography
);
TextTheme
textTheme
=
themeData
.
textTheme
;
return
GptMarkdownThemeData
.
_fromTheme
(
themeData
,
textTheme
).
copyWith
(
highlightColor:
highlightColor
,
...
...
@@ -72,7 +71,9 @@ class GptMarkdownThemeData extends ThemeExtension<GptMarkdownThemeData> {
}
factory
GptMarkdownThemeData
.
_fromTheme
(
ThemeData
theme
,
TextTheme
textTheme
)
{
ThemeData
theme
,
TextTheme
textTheme
,
)
{
return
GptMarkdownThemeData
.
_
(
highlightColor:
theme
.
colorScheme
.
onSurfaceVariant
.
withAlpha
(
50
),
h1:
textTheme
.
headlineLarge
,
...
...
@@ -144,8 +145,10 @@ class GptMarkdownThemeData extends ThemeExtension<GptMarkdownThemeData> {
h4:
TextStyle
.
lerp
(
h4
,
other
.
h4
,
t
)
??
h4
,
h5:
TextStyle
.
lerp
(
h5
,
other
.
h5
,
t
)
??
h5
,
h6:
TextStyle
.
lerp
(
h6
,
other
.
h6
,
t
)
??
h6
,
hrLineThickness:
Tween
(
begin:
hrLineThickness
,
end:
other
.
hrLineThickness
)
.
transform
(
t
),
hrLineThickness:
Tween
(
begin:
hrLineThickness
,
end:
other
.
hrLineThickness
,
).
transform
(
t
),
hrLineColor:
Color
.
lerp
(
hrLineColor
,
other
.
hrLineColor
,
t
)
??
hrLineColor
,
linkColor:
Color
.
lerp
(
linkColor
,
other
.
linkColor
,
t
)
??
linkColor
,
linkHoverColor:
...
...
pubspec.yaml
View file @
a05f9cc
name
:
gpt_markdown
description
:
"
Powerful
Markdown
&
LaTeX
Renderer
for
Flutter:
Rich
Text,
Math,
Tables,
Links,
and
Text
Selection.
Ideal
for
ChatGPT,
Gemini,
and
more."
version
:
1.0.1
0
version
:
1.0.1
1
homepage
:
https://github.com/Infinitix-LLC/gpt_markdown
environment
:
...
...
Please
register
or
login
to post a comment