@@ -90,7 +90,6 @@ struct CompileContext<'a> {
90
90
// compile markdown.
91
91
character_reference_marker : u8 ,
92
92
gfm_table_inside : bool ,
93
- gfm_task_list_item_check_after : bool ,
94
93
hard_break_after : bool ,
95
94
heading_setext_text_after : bool ,
96
95
jsx_tag_stack : Vec < JsxTag > ,
@@ -128,7 +127,6 @@ impl<'a> CompileContext<'a> {
128
127
bytes,
129
128
character_reference_marker : 0 ,
130
129
gfm_table_inside : false ,
131
- gfm_task_list_item_check_after : false ,
132
130
hard_break_after : false ,
133
131
heading_setext_text_after : false ,
134
132
jsx_tag_stack : vec ! [ ] ,
@@ -347,7 +345,6 @@ fn exit(context: &mut CompileContext) -> Result<(), String> {
347
345
| Name :: GfmTableRow
348
346
| Name :: GfmTableCell
349
347
| Name :: HeadingAtx
350
- | Name :: ListItem
351
348
| Name :: ListOrdered
352
349
| Name :: ListUnordered
353
350
| Name :: Paragraph
@@ -358,6 +355,7 @@ fn exit(context: &mut CompileContext) -> Result<(), String> {
358
355
Name :: CharacterEscapeValue
359
356
| Name :: CodeFlowChunk
360
357
| Name :: CodeTextData
358
+ | Name :: Data
361
359
| Name :: FrontmatterChunk
362
360
| Name :: HtmlFlowData
363
361
| Name :: HtmlTextData
@@ -385,7 +383,6 @@ fn exit(context: &mut CompileContext) -> Result<(), String> {
385
383
Name :: CodeFenced | Name :: MathFlow => on_exit_raw_flow ( context) ?,
386
384
Name :: CodeIndented => on_exit_code_indented ( context) ?,
387
385
Name :: CodeText | Name :: MathText => on_exit_raw_text ( context) ?,
388
- Name :: Data => on_exit_data_actual ( context) ?,
389
386
Name :: DefinitionDestinationString => on_exit_definition_destination_string ( context) ,
390
387
Name :: DefinitionLabelString | Name :: GfmFootnoteDefinitionLabelString => {
391
388
on_exit_definition_id ( context) ;
@@ -399,7 +396,6 @@ fn exit(context: &mut CompileContext) -> Result<(), String> {
399
396
| Name :: GfmAutolinkLiteralXmpp => on_exit_gfm_autolink_literal ( context) ?,
400
397
Name :: GfmFootnoteCall | Name :: Image | Name :: Link => on_exit_media ( context) ?,
401
398
Name :: GfmTable => on_exit_gfm_table ( context) ?,
402
- Name :: GfmTaskListItemCheck => on_exit_gfm_task_list_item_check ( context) ,
403
399
Name :: GfmTaskListItemValueUnchecked | Name :: GfmTaskListItemValueChecked => {
404
400
on_exit_gfm_task_list_item_value ( context) ;
405
401
}
@@ -411,6 +407,7 @@ fn exit(context: &mut CompileContext) -> Result<(), String> {
411
407
Name :: HtmlFlow | Name :: HtmlText => on_exit_html ( context) ?,
412
408
Name :: LabelText => on_exit_label_text ( context) ,
413
409
Name :: LineEnding => on_exit_line_ending ( context) ?,
410
+ Name :: ListItem => on_exit_list_item ( context) ?,
414
411
Name :: ListItemValue => on_exit_list_item_value ( context) ,
415
412
Name :: MdxEsm | Name :: MdxFlowExpression | Name :: MdxTextExpression => {
416
413
on_exit_mdx_esm_or_expression ( context) ?;
@@ -1089,29 +1086,6 @@ fn on_exit_data(context: &mut CompileContext) -> Result<(), String> {
1089
1086
Ok ( ( ) )
1090
1087
}
1091
1088
1092
- /// Handle [`Exit`][Kind::Exit]:[`Data`][Name::Data] itself.
1093
- fn on_exit_data_actual ( context : & mut CompileContext ) -> Result < ( ) , String > {
1094
- on_exit_data ( context) ?;
1095
-
1096
- // This field is set when a check exits.
1097
- // When that’s the case, there’s always a `data` event right after it.
1098
- // That data event is the first child (after the check) of the paragraph.
1099
- // We update the text positional info (from the already fixed paragraph),
1100
- // and remove the first byte, which is always a space or tab.
1101
- if context. gfm_task_list_item_check_after {
1102
- let parent = context. tail_mut ( ) ;
1103
- let start = parent. position ( ) . unwrap ( ) . start . clone ( ) ;
1104
- let node = parent. children_mut ( ) . unwrap ( ) . last_mut ( ) . unwrap ( ) ;
1105
- node. position_mut ( ) . unwrap ( ) . start = start;
1106
- if let Node :: Text ( node) = node {
1107
- node. value . remove ( 0 ) ;
1108
- }
1109
- context. gfm_task_list_item_check_after = false ;
1110
- }
1111
-
1112
- Ok ( ( ) )
1113
- }
1114
-
1115
1089
/// Handle [`Exit`][Kind::Exit]:[`DefinitionDestinationString`][Name::DefinitionDestinationString].
1116
1090
fn on_exit_definition_destination_string ( context : & mut CompileContext ) {
1117
1091
let value = context. resume ( ) . to_string ( ) ;
@@ -1210,23 +1184,6 @@ fn on_exit_gfm_table(context: &mut CompileContext) -> Result<(), String> {
1210
1184
Ok ( ( ) )
1211
1185
}
1212
1186
1213
- /// Handle [`Exit`][Kind::Exit]:[`GfmTaskListItemCheck`][Name::GfmTaskListItemCheck].
1214
- fn on_exit_gfm_task_list_item_check ( context : & mut CompileContext ) {
1215
- // This field is set when a check exits.
1216
- // When that’s the case, there’s always a `data` event right after it.
1217
- // That data event is the first child (after the check) of the paragraph.
1218
- // We update the paragraph positional info to start after the check.
1219
- let mut start = point_from_event ( & context. events [ context. index ] ) ;
1220
- debug_assert ! (
1221
- matches!( context. bytes[ start. offset] , b'\t' | b' ' ) ,
1222
- "expected tab or space after check"
1223
- ) ;
1224
- start. column += 1 ;
1225
- start. offset += 1 ;
1226
- context. tail_mut ( ) . position_mut ( ) . unwrap ( ) . start = start;
1227
- context. gfm_task_list_item_check_after = true ;
1228
- }
1229
-
1230
1187
/// Handle [`Exit`][Kind::Exit]:{[`GfmTaskListItemValueChecked`][Name::GfmTaskListItemValueChecked],[`GfmTaskListItemValueUnchecked`][Name::GfmTaskListItemValueUnchecked]}.
1231
1188
fn on_exit_gfm_task_list_item_value ( context : & mut CompileContext ) {
1232
1189
let checked = context. events [ context. index ] . name == Name :: GfmTaskListItemValueChecked ;
@@ -1416,6 +1373,51 @@ fn on_exit_media(context: &mut CompileContext) -> Result<(), String> {
1416
1373
Ok ( ( ) )
1417
1374
}
1418
1375
1376
+ /// Handle [`Exit`][Kind::Exit]:[`ListItem`][Name::ListItem].
1377
+ fn on_exit_list_item ( context : & mut CompileContext ) -> Result < ( ) , String > {
1378
+ if let Node :: ListItem ( item) = context. tail_mut ( ) {
1379
+ if item. checked . is_some ( ) {
1380
+ if let Some ( Node :: Paragraph ( paragraph) ) = item. children . first_mut ( ) {
1381
+ if let Some ( Node :: Text ( text) ) = paragraph. children . first_mut ( ) {
1382
+ let mut point = text. position . as_ref ( ) . unwrap ( ) . start . clone ( ) ;
1383
+ let bytes = text. value . as_bytes ( ) ;
1384
+ let mut start = 0 ;
1385
+
1386
+ // Move past eol.
1387
+ if matches ! ( bytes[ 0 ] , b'\t' | b' ' ) {
1388
+ point. offset += 1 ;
1389
+ point. column += 1 ;
1390
+ start += 1 ;
1391
+ } else if matches ! ( bytes[ 0 ] , b'\r' | b'\n' ) {
1392
+ point. line += 1 ;
1393
+ point. column = 1 ;
1394
+ point. offset += 1 ;
1395
+ start += 1 ;
1396
+ // Move past the LF of CRLF.
1397
+ if bytes. len ( ) > 1 && bytes[ 0 ] == b'\r' && bytes[ 1 ] == b'\n' {
1398
+ point. offset += 1 ;
1399
+ start += 1 ;
1400
+ }
1401
+ }
1402
+
1403
+ // The whole text is whitespace: update the text.
1404
+ if start == bytes. len ( ) {
1405
+ paragraph. children . remove ( 0 ) ;
1406
+ } else {
1407
+ text. value = str:: from_utf8 ( & bytes[ start..] ) . unwrap ( ) . into ( ) ;
1408
+ text. position . as_mut ( ) . unwrap ( ) . start = point. clone ( ) ;
1409
+ }
1410
+ paragraph. position . as_mut ( ) . unwrap ( ) . start = point;
1411
+ }
1412
+ }
1413
+ }
1414
+ }
1415
+
1416
+ on_exit ( context) ?;
1417
+
1418
+ Ok ( ( ) )
1419
+ }
1420
+
1419
1421
/// Handle [`Exit`][Kind::Exit]:[`ListItemValue`][Name::ListItemValue].
1420
1422
fn on_exit_list_item_value ( context : & mut CompileContext ) {
1421
1423
let start = Slice :: from_position (
0 commit comments