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 };
245 ind += 4;
246 }
247 Event::End(v) => {
248 ind -= 4;
249 match v {
250 TagEnd::Paragraph => {
251 info!("{}/Paragraph {:?}", " ".repeat(ind), r.clone(),);
252 }
253 TagEnd::Heading(level) => {
254 info!(
255 "{}/Heading Level={:?} {:?} ",
256 " ".repeat(ind),
257 level,
258 r.clone(),
259 );
260 }
261 TagEnd::BlockQuote(kind) => {
262 info!(
263 "{}/BlockQuote Kind={:?} {:?}",
264 " ".repeat(ind),
265 kind,
266 r.clone(),
267 );
268 }
269 TagEnd::CodeBlock => {
270 info!("{}/CodeBlock {:?} ", " ".repeat(ind), r.clone(),);
271 }
272 TagEnd::HtmlBlock => {
273 info!("{}/HtmlBlock {:?} ", " ".repeat(ind), r.clone(),);
274 }
275 TagEnd::List(ordered) => {
276 info!(
277 "{}/List Ordered={:?} {:?}",
278 " ".repeat(ind),
279 ordered,
280 r.clone(),
281 );
282 }
283 TagEnd::Item => {
284 info!("{}/Item {:?} ", " ".repeat(ind), r.clone(),);
285 }
286 TagEnd::FootnoteDefinition => {
287 info!("{}/FootnoteDefinition {:?}", " ".repeat(ind), r.clone(),);
288 }
289 TagEnd::DefinitionList => {
290 info!("{}/DefinitionList {:?}", " ".repeat(ind), r.clone(),);
291 }
292 TagEnd::DefinitionListTitle => {
293 info!("{}/DefinitionListTitle {:?}", " ".repeat(ind), r.clone(),);
294 }
295 TagEnd::DefinitionListDefinition => {
296 info!(
297 "{}/DefinitionListDefinition {:?}",
298 " ".repeat(ind),
299 r.clone(),
300 );
301 }
302 TagEnd::Table => {
303 info!("{}/Table {:?}", " ".repeat(ind), r.clone(),);
304 }
305 TagEnd::TableHead => {
306 info!("{}/TableHead {:?}", " ".repeat(ind), r.clone(),);
307 }
308 TagEnd::TableRow => {
309 info!("{}/TableRow {:?}", " ".repeat(ind), r.clone(),);
310 }
311 TagEnd::TableCell => {
312 info!("{}/TableCell {:?}", " ".repeat(ind), r.clone(),);
313 }
314 TagEnd::Emphasis => {
315 info!(
316 "{}/Emphasis {:?} {:?}",
317 " ".repeat(ind),
318 r.clone(),
319 &txt[r.clone()]
320 );
321 }
322 TagEnd::Strong => {
323 info!(
324 "{}/Strong {:?} {:?}",
325 " ".repeat(ind),
326 r.clone(),
327 &txt[r.clone()]
328 );
329 }
330 TagEnd::Strikethrough => {
331 info!(
332 "{}/Strikethrough {:?} {:?}",
333 " ".repeat(ind),
334 r.clone(),
335 &txt[r.clone()]
336 );
337 }
338 TagEnd::Link => {
339 info!(
340 "{}/Link {:?} {:?}",
341 " ".repeat(ind),
342 r.clone(),
343 &txt[r.clone()]
344 );
345 }
346 TagEnd::Image => {
347 info!(
348 "{}/Image {:?} {:?}",
349 " ".repeat(ind),
350 r.clone(),
351 &txt[r.clone()]
352 );
353 }
354 TagEnd::MetadataBlock(kind) => {
355 info!(
356 "{}/MetadataBlock Kind={:?} {:?} {:?}",
357 " ".repeat(ind),
358 kind,
359 r.clone(),
360 &txt[r.clone()]
361 );
362 }
363 }
364 }
365 Event::Text(_v) => {
366 info!(
367 "{}Text {:?} {:?}",
368 " ".repeat(ind),
369 r.clone(),
370 &txt[r.clone()]
371 );
372 }
373 Event::Code(v) => {
374 info!(
375 "{}Code V={:?} {:?} {:?}",
376 " ".repeat(ind),
377 v.as_ref(),
378 r.clone(),
379 &txt[r.clone()]
380 );
381 }
382 Event::InlineMath(v) => {
383 info!(
384 "{}InlineMath V={:?} {:?} {:?}",
385 " ".repeat(ind),
386 v.as_ref(),
387 r.clone(),
388 &txt[r.clone()]
389 );
390 }
391 Event::DisplayMath(v) => {
392 info!(
393 "{}DisplayMath V={:?} {:?} {:?}",
394 " ".repeat(ind),
395 v.as_ref(),
396 r.clone(),
397 &txt[r.clone()]
398 );
399 }
400 Event::Html(v) => {
401 info!(
402 "{}Html V={:?} {:?} {:?}",
403 " ".repeat(ind),
404 v.as_ref(),
405 r.clone(),
406 &txt[r.clone()]
407 );
408 }
409 Event::InlineHtml(v) => {
410 info!(
411 "{}InlineHtml V={:?} {:?} {:?}",
412 " ".repeat(ind),
413 v.as_ref(),
414 r.clone(),
415 &txt[r.clone()]
416 );
417 }
418 Event::FootnoteReference(v) => {
419 info!(
420 "{}FootnoteReference V={:?} {:?} {:?}",
421 " ".repeat(ind),
422 v.as_ref(),
423 r.clone(),
424 &txt[r.clone()]
425 );
426 }
427 Event::SoftBreak => {
428 info!(
429 "{}SoftBreak {:?} {:?}",
430 " ".repeat(ind),
431 r.clone(),
432 &txt[r.clone()]
433 );
434 }
435 Event::HardBreak => {
436 info!(
437 "{}HardBreak {:?} {:?}",
438 " ".repeat(ind),
439 r.clone(),
440 &txt[r.clone()]
441 );
442 }
443 Event::Rule => {
444 info!(
445 "{}Rule {:?} {:?}",
446 " ".repeat(ind),
447 r.clone(),
448 &txt[r.clone()]
449 );
450 }
451 Event::TaskListMarker(checked) => {
452 info!(
453 "{}TaskListMarker Checked={:?} {:?} {:?}",
454 " ".repeat(ind),
455 checked,
456 r.clone(),
457 &txt[r.clone()]
458 );
459 }
460 }
461 }
462
463 let rdef = it.reference_definitions();
464 for (rstr, rdef) in rdef.iter() {
465 info!(
466 "ReferenceDefinition {:?} {:?} = {:?} {:?}",
467 rdef.span,
468 rstr,
469 rdef.dest.as_ref(),
470 rdef.title.as_ref().map(|v| v.as_ref())
471 )
472 }
473}