@@ -189,6 +189,130 @@ pub enum Item {
189
189
} ,
190
190
}
191
191
192
+ impl Item {
193
+ /// Displays a Markdown [`Item`] using the default, built-in look for its children.
194
+ pub fn view < ' a , ' b , Theme , Renderer > (
195
+ & ' b self ,
196
+ settings : Settings ,
197
+ style : Style ,
198
+ index : usize ,
199
+ ) -> Element < ' a , Url , Theme , Renderer >
200
+ where
201
+ Theme : Catalog + ' a ,
202
+ Renderer : core:: text:: Renderer < Font = Font > + ' a ,
203
+ {
204
+ self . view_with ( index, settings, style, & DefaultView )
205
+ }
206
+
207
+ /// Displays a Markdown [`Item`] using the given [`View`] for its children.
208
+ pub fn view_with < ' a , ' b , Theme , Renderer > (
209
+ & ' b self ,
210
+ index : usize ,
211
+ settings : Settings ,
212
+ style : Style ,
213
+ view : & dyn View < ' a , ' b , Url , Theme , Renderer > ,
214
+ ) -> Element < ' a , Url , Theme , Renderer >
215
+ where
216
+ Theme : Catalog + ' a ,
217
+ Renderer : core:: text:: Renderer < Font = Font > + ' a ,
218
+ {
219
+ let Settings {
220
+ text_size,
221
+ h1_size,
222
+ h2_size,
223
+ h3_size,
224
+ h4_size,
225
+ h5_size,
226
+ h6_size,
227
+ code_size,
228
+ spacing,
229
+ } = settings;
230
+
231
+ match self {
232
+ Item :: Heading ( level, heading) => {
233
+ container ( rich_text ( heading. spans ( style) ) . size ( match level {
234
+ pulldown_cmark:: HeadingLevel :: H1 => h1_size,
235
+ pulldown_cmark:: HeadingLevel :: H2 => h2_size,
236
+ pulldown_cmark:: HeadingLevel :: H3 => h3_size,
237
+ pulldown_cmark:: HeadingLevel :: H4 => h4_size,
238
+ pulldown_cmark:: HeadingLevel :: H5 => h5_size,
239
+ pulldown_cmark:: HeadingLevel :: H6 => h6_size,
240
+ } ) )
241
+ . padding ( padding:: top ( if index > 0 {
242
+ text_size / 2.0
243
+ } else {
244
+ Pixels :: ZERO
245
+ } ) )
246
+ . into ( )
247
+ }
248
+ Item :: Paragraph ( paragraph) => {
249
+ rich_text ( paragraph. spans ( style) ) . size ( text_size) . into ( )
250
+ }
251
+ Item :: List { start : None , items } => {
252
+ column ( items. iter ( ) . map ( |items| {
253
+ row ! [
254
+ text( "•" ) . size( text_size) ,
255
+ view_with(
256
+ items,
257
+ Settings {
258
+ spacing: settings. spacing * 0.6 ,
259
+ ..settings
260
+ } ,
261
+ style,
262
+ view
263
+ )
264
+ ]
265
+ . spacing ( spacing)
266
+ . into ( )
267
+ } ) )
268
+ . spacing ( spacing * 0.75 )
269
+ . into ( )
270
+ }
271
+ Item :: List {
272
+ start : Some ( start) ,
273
+ items,
274
+ } => column ( items. iter ( ) . enumerate ( ) . map ( |( i, items) | {
275
+ row ! [
276
+ text!( "{}." , i as u64 + * start) . size( text_size) ,
277
+ view_with(
278
+ items,
279
+ Settings {
280
+ spacing: settings. spacing * 0.6 ,
281
+ ..settings
282
+ } ,
283
+ style,
284
+ view
285
+ )
286
+ ]
287
+ . spacing ( spacing)
288
+ . into ( )
289
+ } ) )
290
+ . spacing ( spacing * 0.75 )
291
+ . into ( ) ,
292
+ Item :: CodeBlock ( lines) => container (
293
+ scrollable (
294
+ container ( column ( lines. iter ( ) . map ( |line| {
295
+ rich_text ( line. spans ( style) )
296
+ . font ( Font :: MONOSPACE )
297
+ . size ( code_size)
298
+ . into ( )
299
+ } ) ) )
300
+ . padding ( spacing. 0 / 2.0 ) ,
301
+ )
302
+ . direction ( scrollable:: Direction :: Horizontal (
303
+ scrollable:: Scrollbar :: default ( )
304
+ . width ( spacing. 0 / 2.0 )
305
+ . scroller_width ( spacing. 0 / 2.0 ) ,
306
+ ) ) ,
307
+ )
308
+ . width ( Length :: Fill )
309
+ . padding ( spacing. 0 / 2.0 )
310
+ . class ( Theme :: code_block ( ) )
311
+ . into ( ) ,
312
+ }
313
+ }
314
+ }
315
+
192
316
/// A bunch of parsed Markdown text.
193
317
#[ derive( Debug , Clone ) ]
194
318
pub struct Text {
@@ -900,100 +1024,68 @@ where
900
1024
Theme : Catalog + ' a ,
901
1025
Renderer : core:: text:: Renderer < Font = Font > + ' a ,
902
1026
{
903
- let Settings {
904
- text_size,
905
- h1_size,
906
- h2_size,
907
- h3_size,
908
- h4_size,
909
- h5_size,
910
- h6_size,
911
- code_size,
912
- spacing,
913
- } = settings;
914
-
915
- let blocks = items. into_iter ( ) . enumerate ( ) . map ( |( i, item) | match item {
916
- Item :: Heading ( level, heading) => {
917
- container ( rich_text ( heading. spans ( style) ) . size ( match level {
918
- pulldown_cmark:: HeadingLevel :: H1 => h1_size,
919
- pulldown_cmark:: HeadingLevel :: H2 => h2_size,
920
- pulldown_cmark:: HeadingLevel :: H3 => h3_size,
921
- pulldown_cmark:: HeadingLevel :: H4 => h4_size,
922
- pulldown_cmark:: HeadingLevel :: H5 => h5_size,
923
- pulldown_cmark:: HeadingLevel :: H6 => h6_size,
924
- } ) )
925
- . padding ( padding:: top ( if i > 0 {
926
- text_size / 2.0
927
- } else {
928
- Pixels :: ZERO
929
- } ) )
930
- . into ( )
931
- }
932
- Item :: Paragraph ( paragraph) => {
933
- rich_text ( paragraph. spans ( style) ) . size ( text_size) . into ( )
934
- }
935
- Item :: List { start : None , items } => {
936
- column ( items. iter ( ) . map ( |items| {
937
- row ! [
938
- text( "•" ) . size( text_size) ,
939
- view(
940
- items,
941
- Settings {
942
- spacing: settings. spacing * 0.6 ,
943
- ..settings
944
- } ,
945
- style
946
- )
947
- ]
948
- . spacing ( spacing)
949
- . into ( )
950
- } ) )
951
- . spacing ( spacing * 0.75 )
952
- . into ( )
953
- }
954
- Item :: List {
955
- start : Some ( start) ,
956
- items,
957
- } => column ( items. iter ( ) . enumerate ( ) . map ( |( i, items) | {
958
- row ! [
959
- text!( "{}." , i as u64 + * start) . size( text_size) ,
960
- view(
961
- items,
962
- Settings {
963
- spacing: settings. spacing * 0.6 ,
964
- ..settings
965
- } ,
966
- style
967
- )
968
- ]
969
- . spacing ( spacing)
970
- . into ( )
971
- } ) )
972
- . spacing ( spacing * 0.75 )
973
- . into ( ) ,
974
- Item :: CodeBlock ( lines) => container (
975
- scrollable (
976
- container ( column ( lines. iter ( ) . map ( |line| {
977
- rich_text ( line. spans ( style) )
978
- . font ( Font :: MONOSPACE )
979
- . size ( code_size)
980
- . into ( )
981
- } ) ) )
982
- . padding ( spacing. 0 / 2.0 ) ,
983
- )
984
- . direction ( scrollable:: Direction :: Horizontal (
985
- scrollable:: Scrollbar :: default ( )
986
- . width ( spacing. 0 / 2.0 )
987
- . scroller_width ( spacing. 0 / 2.0 ) ,
988
- ) ) ,
989
- )
990
- . width ( Length :: Fill )
991
- . padding ( spacing. 0 / 2.0 )
992
- . class ( Theme :: code_block ( ) )
993
- . into ( ) ,
994
- } ) ;
995
-
996
- Element :: new ( column ( blocks) . spacing ( spacing) )
1027
+ view_with ( items, settings, style, & DefaultView )
1028
+ }
1029
+
1030
+ /// Runs [`view`] but with a custom [`View`] to turn an [`Item`] into
1031
+ /// an [`Element`].
1032
+ ///
1033
+ /// This is useful if you want to customize the look of certain Markdown
1034
+ /// elements.
1035
+ ///
1036
+ /// You can use [`Item::view`] and [`Item::view_with`] for the default
1037
+ /// look.
1038
+ pub fn view_with < ' a , ' b , Message , Theme , Renderer > (
1039
+ items : impl IntoIterator < Item = & ' b Item > ,
1040
+ settings : Settings ,
1041
+ style : Style ,
1042
+ view : & dyn View < ' a , ' b , Message , Theme , Renderer > ,
1043
+ ) -> Element < ' a , Message , Theme , Renderer >
1044
+ where
1045
+ Message : ' a ,
1046
+ Theme : Catalog + ' a ,
1047
+ Renderer : core:: text:: Renderer < Font = Font > + ' a ,
1048
+ {
1049
+ let blocks = items
1050
+ . into_iter ( )
1051
+ . enumerate ( )
1052
+ . map ( move |( i, item) | view. view ( settings, style, item, i) ) ;
1053
+
1054
+ Element :: new ( column ( blocks) . spacing ( settings. spacing ) )
1055
+ }
1056
+
1057
+ /// A view strategy to display a Markdown [`Item`].
1058
+ pub trait View < ' a , ' b , Message , Theme , Renderer > {
1059
+ /// Displays a Markdown [`Item`] by projecting it into an [`Element`].
1060
+ ///
1061
+ /// You can use [`Item::view`] and [`Item::view_with`] for the default
1062
+ /// look.
1063
+ fn view (
1064
+ & self ,
1065
+ settings : Settings ,
1066
+ style : Style ,
1067
+ item : & ' b Item ,
1068
+ index : usize ,
1069
+ ) -> Element < ' a , Message , Theme , Renderer > ;
1070
+ }
1071
+
1072
+ #[ derive( Debug , Clone , Copy ) ]
1073
+ struct DefaultView ;
1074
+
1075
+ impl < ' a , ' b , Theme , Renderer > View < ' a , ' b , Url , Theme , Renderer > for DefaultView
1076
+ where
1077
+ Theme : Catalog + ' a ,
1078
+ Renderer : core:: text:: Renderer < Font = Font > + ' a ,
1079
+ {
1080
+ fn view (
1081
+ & self ,
1082
+ settings : Settings ,
1083
+ style : Style ,
1084
+ item : & ' b Item ,
1085
+ index : usize ,
1086
+ ) -> Element < ' a , Url , Theme , Renderer > {
1087
+ item. view ( settings, style, index)
1088
+ }
997
1089
}
998
1090
999
1091
/// The theme catalog of Markdown items.
0 commit comments