1use crate::styles::MDStyle;
2use log::info;
3use pulldown_cmark::{Event, Options, Parser, Tag, TagEnd};
4use rat_text::event::TextOutcome;
5use rat_text::text_area::TextAreaState;
6use rat_text::TextRange;
7
8pub fn md_dump_styles(state: &mut TextAreaState) -> TextOutcome {
9 let cursor = state.cursor();
10 let cursor_byte = state.byte_at(cursor).start;
11
12 let mut sty = Vec::new();
13 state.styles_at(cursor_byte, &mut sty);
14 for (_r, s) in sty {
15 info!("style {:?}: {:?}", cursor, MDStyle::try_from(s));
16 }
17
18 TextOutcome::Unchanged
19}
20
21pub fn md_dump(state: &TextAreaState) -> TextOutcome {
22 let cursor = state.cursor();
23 let cursor_byte = state.byte_at(cursor).start;
24
25 let selection = if state.selection().is_empty() {
26 let mut sty = Vec::new();
27 state.styles_at(cursor_byte, &mut sty);
28
29 let first = sty
30 .iter()
31 .filter(|(_, s)| {
32 matches!(
33 MDStyle::try_from(*s).expect("fine"),
34 MDStyle::Heading1
35 | MDStyle::Heading2
36 | MDStyle::Heading3
37 | MDStyle::Heading4
38 | MDStyle::Heading5
39 | MDStyle::Heading6
40 | MDStyle::Paragraph
41 | MDStyle::BlockQuote
42 | MDStyle::CodeBlock
43 | MDStyle::MathDisplay
44 | MDStyle::Rule
45 | MDStyle::Html
46 | MDStyle::FootnoteDefinition
47 | MDStyle::List
48 | MDStyle::DefinitionList
49 | MDStyle::Table
50 )
51 })
52 .next();
53
54 if let Some((r, _)) = first {
55 let r = state.byte_range(r.clone());
56 TextRange::new((0, r.start.y), r.end)
57 } else {
58 TextRange::new((0, cursor.y), (0, cursor.y + 1))
59 }
60 } else {
61 TextRange::new(
62 (0, state.selection().start.y),
63 (0, state.selection().end.y + 1),
64 )
65 };
66
67 dump_md(state.str_slice(selection).as_ref());
68
69 TextOutcome::Unchanged
70}
71
72fn dump_md(txt: &str) {
73 info!("*** DUMP ***");
74 info!("{:?}", txt);
75
76 let mut it = Parser::new_ext(
77 txt,
78 Options::ENABLE_MATH
79 | Options::ENABLE_TASKLISTS
80 | Options::ENABLE_TABLES
81 | Options::ENABLE_STRIKETHROUGH
82 | Options::ENABLE_SMART_PUNCTUATION
83 | Options::ENABLE_FOOTNOTES
84 | Options::ENABLE_GFM
85 | Options::ENABLE_DEFINITION_LIST,
86 )
87 .into_offset_iter();
88
89 let mut ind = 0;
90 loop {
91 let Some((e, r)) = it.next() else {
92 break;
93 };
94
95 match e {
96 Event::Start(v) => {
97 match v {
98 Tag::Paragraph => {
99 info!("{}Paragraph {:?}", " ".repeat(ind), r.clone(),);
100 }
101 Tag::Heading {
102 level,
103 id,
104 classes: _todo_classes_,
105 attrs: _todo_attrs_,
106 } => {
107 info!(
108 "{}Heading Level={:?} Id={:?} {:?}",
109 " ".repeat(ind),
110 level,
111 id,
112 r.clone(),
113 );
114 }
115 Tag::BlockQuote(kind) => {
116 info!(
117 "{}BlockQuote Kind={:?} {:?}",
118 " ".repeat(ind),
119 kind,
120 r.clone(),
121 );
122 }
123 Tag::CodeBlock(kind) => {
124 info!(
125 "{}CodeBlock Kind={:?} {:?}",
126 " ".repeat(ind),
127 kind,
128 r.clone(),
129 );
130 }
131 Tag::HtmlBlock => {
132 info!("{}HtmlBlock {:?}", " ".repeat(ind), r.clone(),);
133 }
134 Tag::List(first) => {
135 info!("{}List First={:?} {:?}", " ".repeat(ind), first, r.clone(),);
136 }
137 Tag::Item => {
138 info!("{}Item {:?}", " ".repeat(ind), r.clone(),);
139 }
140 Tag::FootnoteDefinition(label) => {
141 info!(
142 "{}FootnoteDefinition Label={:?} {:?}",
143 " ".repeat(ind),
144 label,
145 r.clone(),
146 );
147 }
148 Tag::DefinitionList => {
149 info!("{}DefinitionList {:?}", " ".repeat(ind), r.clone(),);
150 }
151 Tag::DefinitionListTitle => {
152 info!("{}DefinitionListTitle {:?}", " ".repeat(ind), r.clone(),);
153 }
154 Tag::DefinitionListDefinition => {
155 info!(
156 "{}DefinitionListDefinition {:?}",
157 " ".repeat(ind),
158 r.clone(),
159 );
160 }
161 Tag::Table(align) => {
162 info!(
163 "{}Table Alignment={:?} {:?}",
164 " ".repeat(ind),
165 align,
166 r.clone(),
167 );
168 }
169 Tag::TableHead => {
170 info!("{}TableHead {:?}", " ".repeat(ind), r.clone(),);
171 }
172 Tag::TableRow => {
173 info!("{}TableRow {:?}", " ".repeat(ind), r.clone(),);
174 }
175 Tag::TableCell => {
176 info!("{}TableCell {:?}", " ".repeat(ind), r.clone(),);
177 }
178 Tag::Emphasis => {
179 info!(
180 "{}Emphasis {:?} {:?}",
181 " ".repeat(ind),
182 r.clone(),
183 &txt[r.clone()]
184 );
185 }
186 Tag::Strong => {
187 info!(
188 "{}Strong {:?} {:?}",
189 " ".repeat(ind),
190 r.clone(),
191 &txt[r.clone()]
192 );
193 }
194 Tag::Strikethrough => {
195 info!(
196 "{}Strikethrough {:?} {:?}",
197 " ".repeat(ind),
198 r.clone(),
199 &txt[r.clone()]
200 );
201 }
202 Tag::Link {
203 link_type,
204 dest_url,
205 title,
206 id,
207 } => {
208 info!(
209 "{}Link LinkType={:?} DestUrl={:?} Title={:?} Id={:?} {:?} {:?}",
210 " ".repeat(ind),
211 link_type,
212 dest_url,
213 title,
214 id,
215 r.clone(),
216 &txt[r.clone()]
217 );
218 }
219 Tag::Image {
220 link_type,
221 dest_url,
222 title,
223 id,
224 } => {
225 info!(
226 "{}Image LinkType={:?} DestUrl={:?} Title={:?} Id={:?} {:?} {:?}",
227 " ".repeat(ind),
228 link_type,
229 dest_url,
230 title,
231 id,
232 r.clone(),
233 &txt[r.clone()]
234 );
235 }
236 Tag::MetadataBlock(kind) => {
237 info!(
238 "{}MetadataBlock Kind={:?} {:?} {:?}",
239 " ".repeat(ind),
240 kind,
241 r.clone(),
242 &txt[r.clone()]
243 );
244 }
245 };
246 ind += 4;
247 }
248 Event::End(v) => {
249 ind -= 4;
250 match v {
251 TagEnd::Paragraph => {
252 info!("{}/Paragraph {:?}", " ".repeat(ind), r.clone(),);
253 }
254 TagEnd::Heading(level) => {
255 info!(
256 "{}/Heading Level={:?} {:?} ",
257 " ".repeat(ind),
258 level,
259 r.clone(),
260 );
261 }
262 TagEnd::BlockQuote(kind) => {
263 info!(
264 "{}/BlockQuote Kind={:?} {:?}",
265 " ".repeat(ind),
266 kind,
267 r.clone(),
268 );
269 }
270 TagEnd::CodeBlock => {
271 info!("{}/CodeBlock {:?} ", " ".repeat(ind), r.clone(),);
272 }
273 TagEnd::HtmlBlock => {
274 info!("{}/HtmlBlock {:?} ", " ".repeat(ind), r.clone(),);
275 }
276 TagEnd::List(ordered) => {
277 info!(
278 "{}/List Ordered={:?} {:?}",
279 " ".repeat(ind),
280 ordered,
281 r.clone(),
282 );
283 }
284 TagEnd::Item => {
285 info!("{}/Item {:?} ", " ".repeat(ind), r.clone(),);
286 }
287 TagEnd::FootnoteDefinition => {
288 info!("{}/FootnoteDefinition {:?}", " ".repeat(ind), r.clone(),);
289 }
290 TagEnd::DefinitionList => {
291 info!("{}/DefinitionList {:?}", " ".repeat(ind), r.clone(),);
292 }
293 TagEnd::DefinitionListTitle => {
294 info!("{}/DefinitionListTitle {:?}", " ".repeat(ind), r.clone(),);
295 }
296 TagEnd::DefinitionListDefinition => {
297 info!(
298 "{}/DefinitionListDefinition {:?}",
299 " ".repeat(ind),
300 r.clone(),
301 );
302 }
303 TagEnd::Table => {
304 info!("{}/Table {:?}", " ".repeat(ind), r.clone(),);
305 }
306 TagEnd::TableHead => {
307 info!("{}/TableHead {:?}", " ".repeat(ind), r.clone(),);
308 }
309 TagEnd::TableRow => {
310 info!("{}/TableRow {:?}", " ".repeat(ind), r.clone(),);
311 }
312 TagEnd::TableCell => {
313 info!("{}/TableCell {:?}", " ".repeat(ind), r.clone(),);
314 }
315 TagEnd::Emphasis => {
316 info!(
317 "{}/Emphasis {:?} {:?}",
318 " ".repeat(ind),
319 r.clone(),
320 &txt[r.clone()]
321 );
322 }
323 TagEnd::Strong => {
324 info!(
325 "{}/Strong {:?} {:?}",
326 " ".repeat(ind),
327 r.clone(),
328 &txt[r.clone()]
329 );
330 }
331 TagEnd::Strikethrough => {
332 info!(
333 "{}/Strikethrough {:?} {:?}",
334 " ".repeat(ind),
335 r.clone(),
336 &txt[r.clone()]
337 );
338 }
339 TagEnd::Link => {
340 info!(
341 "{}/Link {:?} {:?}",
342 " ".repeat(ind),
343 r.clone(),
344 &txt[r.clone()]
345 );
346 }
347 TagEnd::Image => {
348 info!(
349 "{}/Image {:?} {:?}",
350 " ".repeat(ind),
351 r.clone(),
352 &txt[r.clone()]
353 );
354 }
355 TagEnd::MetadataBlock(kind) => {
356 info!(
357 "{}/MetadataBlock Kind={:?} {:?} {:?}",
358 " ".repeat(ind),
359 kind,
360 r.clone(),
361 &txt[r.clone()]
362 );
363 }
364 }
365 }
366 Event::Text(_v) => {
367 info!(
368 "{}Text {:?} {:?}",
369 " ".repeat(ind),
370 r.clone(),
371 &txt[r.clone()]
372 );
373 }
374 Event::Code(v) => {
375 info!(
376 "{}Code V={:?} {:?} {:?}",
377 " ".repeat(ind),
378 v.as_ref(),
379 r.clone(),
380 &txt[r.clone()]
381 );
382 }
383 Event::InlineMath(v) => {
384 info!(
385 "{}InlineMath V={:?} {:?} {:?}",
386 " ".repeat(ind),
387 v.as_ref(),
388 r.clone(),
389 &txt[r.clone()]
390 );
391 }
392 Event::DisplayMath(v) => {
393 info!(
394 "{}DisplayMath V={:?} {:?} {:?}",
395 " ".repeat(ind),
396 v.as_ref(),
397 r.clone(),
398 &txt[r.clone()]
399 );
400 }
401 Event::Html(v) => {
402 info!(
403 "{}Html V={:?} {:?} {:?}",
404 " ".repeat(ind),
405 v.as_ref(),
406 r.clone(),
407 &txt[r.clone()]
408 );
409 }
410 Event::InlineHtml(v) => {
411 info!(
412 "{}InlineHtml V={:?} {:?} {:?}",
413 " ".repeat(ind),
414 v.as_ref(),
415 r.clone(),
416 &txt[r.clone()]
417 );
418 }
419 Event::FootnoteReference(v) => {
420 info!(
421 "{}FootnoteReference V={:?} {:?} {:?}",
422 " ".repeat(ind),
423 v.as_ref(),
424 r.clone(),
425 &txt[r.clone()]
426 );
427 }
428 Event::SoftBreak => {
429 info!(
430 "{}SoftBreak {:?} {:?}",
431 " ".repeat(ind),
432 r.clone(),
433 &txt[r.clone()]
434 );
435 }
436 Event::HardBreak => {
437 info!(
438 "{}HardBreak {:?} {:?}",
439 " ".repeat(ind),
440 r.clone(),
441 &txt[r.clone()]
442 );
443 }
444 Event::Rule => {
445 info!(
446 "{}Rule {:?} {:?}",
447 " ".repeat(ind),
448 r.clone(),
449 &txt[r.clone()]
450 );
451 }
452 Event::TaskListMarker(checked) => {
453 info!(
454 "{}TaskListMarker Checked={:?} {:?} {:?}",
455 " ".repeat(ind),
456 checked,
457 r.clone(),
458 &txt[r.clone()]
459 );
460 }
461 }
462 }
463
464 let rdef = it.reference_definitions();
465 for (rstr, rdef) in rdef.iter() {
466 info!(
467 "ReferenceDefinition {:?} {:?} = {:?} {:?}",
468 rdef.span,
469 rstr,
470 rdef.dest.as_ref(),
471 rdef.title.as_ref().map(|v| v.as_ref())
472 )
473 }
474}