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