1use std::collections::{HashMap, HashSet};
2use std::sync::Arc;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
9pub enum Flavor {
10 #[default]
12 Pandoc,
13 Quarto,
15 #[cfg_attr(feature = "serde", serde(rename = "rmarkdown"))]
17 RMarkdown,
18 Gfm,
20 #[cfg_attr(feature = "serde", serde(alias = "commonmark"))]
22 CommonMark,
23 #[cfg_attr(feature = "serde", serde(rename = "multimarkdown"))]
25 MultiMarkdown,
26}
27
28#[derive(Debug, Clone, PartialEq)]
32#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
33#[cfg_attr(feature = "serde", serde(default))]
34#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
35#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
36pub struct Extensions {
37 #[cfg_attr(feature = "serde", serde(alias = "blank_before_header"))]
42 pub blank_before_header: bool,
43 #[cfg_attr(feature = "serde", serde(alias = "header_attributes"))]
45 pub header_attributes: bool,
46 pub auto_identifiers: bool,
48 pub gfm_auto_identifiers: bool,
50 pub implicit_header_references: bool,
52
53 #[cfg_attr(feature = "serde", serde(alias = "blank_before_blockquote"))]
56 pub blank_before_blockquote: bool,
57
58 #[cfg_attr(feature = "serde", serde(alias = "fancy_lists"))]
61 pub fancy_lists: bool,
62 pub startnum: bool,
64 #[cfg_attr(feature = "serde", serde(alias = "example_lists"))]
66 pub example_lists: bool,
67 #[cfg_attr(feature = "serde", serde(alias = "task_lists"))]
69 pub task_lists: bool,
70 #[cfg_attr(feature = "serde", serde(alias = "definition_lists"))]
72 pub definition_lists: bool,
73 #[cfg_attr(feature = "serde", serde(alias = "lists_without_preceding_blankline"))]
75 pub lists_without_preceding_blankline: bool,
76
77 #[cfg_attr(feature = "serde", serde(alias = "backtick_code_blocks"))]
80 pub backtick_code_blocks: bool,
81 #[cfg_attr(feature = "serde", serde(alias = "fenced_code_blocks"))]
83 pub fenced_code_blocks: bool,
84 #[cfg_attr(feature = "serde", serde(alias = "fenced_code_attributes"))]
86 pub fenced_code_attributes: bool,
87 pub executable_code: bool,
89 pub rmarkdown_inline_code: bool,
91 pub quarto_inline_code: bool,
93 #[cfg_attr(feature = "serde", serde(alias = "inline_code_attributes"))]
95 pub inline_code_attributes: bool,
96
97 #[cfg_attr(feature = "serde", serde(alias = "simple_tables"))]
100 pub simple_tables: bool,
101 #[cfg_attr(feature = "serde", serde(alias = "multiline_tables"))]
103 pub multiline_tables: bool,
104 #[cfg_attr(feature = "serde", serde(alias = "grid_tables"))]
106 pub grid_tables: bool,
107 #[cfg_attr(feature = "serde", serde(alias = "pipe_tables"))]
109 pub pipe_tables: bool,
110 #[cfg_attr(feature = "serde", serde(alias = "table_captions"))]
112 pub table_captions: bool,
113
114 #[cfg_attr(feature = "serde", serde(alias = "fenced_divs"))]
117 pub fenced_divs: bool,
118 #[cfg_attr(feature = "serde", serde(alias = "native_divs"))]
120 pub native_divs: bool,
121
122 #[cfg_attr(feature = "serde", serde(alias = "line_blocks"))]
125 pub line_blocks: bool,
126
127 #[cfg_attr(feature = "serde", serde(alias = "intraword_underscores"))]
132 pub intraword_underscores: bool,
133 pub strikeout: bool,
135 pub superscript: bool,
137 pub subscript: bool,
138
139 #[cfg_attr(feature = "serde", serde(alias = "inline_links"))]
142 pub inline_links: bool,
143 #[cfg_attr(feature = "serde", serde(alias = "reference_links"))]
145 pub reference_links: bool,
146 #[cfg_attr(feature = "serde", serde(alias = "shortcut_reference_links"))]
148 pub shortcut_reference_links: bool,
149 #[cfg_attr(feature = "serde", serde(alias = "link_attributes"))]
151 pub link_attributes: bool,
152 pub autolinks: bool,
154
155 #[cfg_attr(feature = "serde", serde(alias = "inline_images"))]
158 pub inline_images: bool,
159 #[cfg_attr(feature = "serde", serde(alias = "implicit_figures"))]
161 pub implicit_figures: bool,
162
163 #[cfg_attr(feature = "serde", serde(alias = "tex_math_dollars"))]
166 pub tex_math_dollars: bool,
167 #[cfg_attr(feature = "serde", serde(alias = "tex_math_gfm"))]
169 pub tex_math_gfm: bool,
170 #[cfg_attr(feature = "serde", serde(alias = "tex_math_single_backslash"))]
172 pub tex_math_single_backslash: bool,
173 #[cfg_attr(feature = "serde", serde(alias = "tex_math_double_backslash"))]
175 pub tex_math_double_backslash: bool,
176
177 #[cfg_attr(feature = "serde", serde(alias = "inline_footnotes"))]
180 pub inline_footnotes: bool,
181 pub footnotes: bool,
183
184 pub citations: bool,
187
188 #[cfg_attr(feature = "serde", serde(alias = "bracketed_spans"))]
191 pub bracketed_spans: bool,
192 #[cfg_attr(feature = "serde", serde(alias = "native_spans"))]
194 pub native_spans: bool,
195
196 #[cfg_attr(feature = "serde", serde(alias = "yaml_metadata_block"))]
199 pub yaml_metadata_block: bool,
200 #[cfg_attr(feature = "serde", serde(alias = "pandoc_title_block"))]
202 pub pandoc_title_block: bool,
203 pub mmd_title_block: bool,
205
206 #[cfg_attr(feature = "serde", serde(alias = "raw_html"))]
209 pub raw_html: bool,
210 #[cfg_attr(feature = "serde", serde(alias = "markdown_in_html_blocks"))]
212 pub markdown_in_html_blocks: bool,
213 #[cfg_attr(feature = "serde", serde(alias = "raw_tex"))]
215 pub raw_tex: bool,
216 #[cfg_attr(feature = "serde", serde(alias = "raw_attribute"))]
218 pub raw_attribute: bool,
219
220 #[cfg_attr(feature = "serde", serde(alias = "all_symbols_escapable"))]
223 pub all_symbols_escapable: bool,
224 #[cfg_attr(feature = "serde", serde(alias = "escaped_line_breaks"))]
226 pub escaped_line_breaks: bool,
227
228 #[cfg_attr(feature = "serde", serde(alias = "autolink_bare_uris"))]
232 pub autolink_bare_uris: bool,
233 #[cfg_attr(feature = "serde", serde(alias = "hard_line_breaks"))]
235 pub hard_line_breaks: bool,
236 pub mmd_header_identifiers: bool,
238 pub mmd_link_attributes: bool,
240 pub alerts: bool,
242 pub emoji: bool,
244 pub mark: bool,
246
247 #[cfg_attr(feature = "serde", serde(alias = "quarto_callouts"))]
250 pub quarto_callouts: bool,
251 #[cfg_attr(feature = "serde", serde(alias = "quarto_crossrefs"))]
253 pub quarto_crossrefs: bool,
254 #[cfg_attr(feature = "serde", serde(alias = "quarto_shortcodes"))]
256 pub quarto_shortcodes: bool,
257 pub bookdown_references: bool,
259 pub bookdown_equation_references: bool,
261}
262
263impl Default for Extensions {
264 fn default() -> Self {
265 Self::for_flavor(Flavor::default())
266 }
267}
268
269impl Extensions {
270 fn none_defaults() -> Self {
271 Self {
272 alerts: false,
273 all_symbols_escapable: false,
274 auto_identifiers: false,
275 autolink_bare_uris: false,
276 autolinks: false,
277 backtick_code_blocks: false,
278 blank_before_blockquote: false,
279 blank_before_header: false,
280 bookdown_references: false,
281 bookdown_equation_references: false,
282 bracketed_spans: false,
283 citations: false,
284 definition_lists: false,
285 lists_without_preceding_blankline: false,
286 emoji: false,
287 escaped_line_breaks: false,
288 example_lists: false,
289 executable_code: false,
290 rmarkdown_inline_code: false,
291 quarto_inline_code: false,
292 fancy_lists: false,
293 fenced_code_attributes: false,
294 fenced_code_blocks: false,
295 fenced_divs: false,
296 footnotes: false,
297 gfm_auto_identifiers: false,
298 grid_tables: false,
299 hard_line_breaks: false,
300 header_attributes: false,
301 implicit_figures: false,
302 implicit_header_references: false,
303 inline_code_attributes: false,
304 inline_footnotes: false,
305 inline_images: false,
306 inline_links: false,
307 intraword_underscores: false,
308 line_blocks: false,
309 link_attributes: false,
310 mark: false,
311 markdown_in_html_blocks: false,
312 mmd_header_identifiers: false,
313 mmd_link_attributes: false,
314 mmd_title_block: false,
315 multiline_tables: false,
316 native_divs: false,
317 native_spans: false,
318 pandoc_title_block: false,
319 pipe_tables: false,
320 quarto_callouts: false,
321 quarto_crossrefs: false,
322 quarto_shortcodes: false,
323 raw_attribute: false,
324 raw_html: false,
325 raw_tex: false,
326 reference_links: false,
327 shortcut_reference_links: false,
328 simple_tables: false,
329 startnum: false,
330 strikeout: false,
331 subscript: false,
332 superscript: false,
333 table_captions: false,
334 task_lists: false,
335 tex_math_dollars: false,
336 tex_math_double_backslash: false,
337 tex_math_gfm: false,
338 tex_math_single_backslash: false,
339 yaml_metadata_block: false,
340 }
341 }
342
343 pub fn for_flavor(flavor: Flavor) -> Self {
345 match flavor {
346 Flavor::Pandoc => Self::pandoc_defaults(),
347 Flavor::Quarto => Self::quarto_defaults(),
348 Flavor::RMarkdown => Self::rmarkdown_defaults(),
349 Flavor::Gfm => Self::gfm_defaults(),
350 Flavor::CommonMark => Self::commonmark_defaults(),
351 Flavor::MultiMarkdown => Self::multimarkdown_defaults(),
352 }
353 }
354
355 fn pandoc_defaults() -> Self {
356 Self {
357 auto_identifiers: true,
359 blank_before_blockquote: true,
360 blank_before_header: true,
361 gfm_auto_identifiers: false,
362 header_attributes: true,
363 implicit_header_references: true,
364
365 definition_lists: true,
367 example_lists: true,
368 fancy_lists: true,
369 lists_without_preceding_blankline: false,
370 startnum: true,
371 task_lists: true,
372
373 backtick_code_blocks: true,
375 executable_code: false,
376 rmarkdown_inline_code: false,
377 quarto_inline_code: false,
378 fenced_code_attributes: true,
379 fenced_code_blocks: true,
380 inline_code_attributes: true,
381
382 grid_tables: true,
384 multiline_tables: true,
385 pipe_tables: true,
386 simple_tables: true,
387 table_captions: true,
388
389 fenced_divs: true,
391 native_divs: true,
392
393 line_blocks: true,
395
396 intraword_underscores: true,
398 strikeout: true,
399 subscript: true,
400 superscript: true,
401
402 autolinks: true,
404 inline_links: true,
405 link_attributes: true,
406 reference_links: true,
407 shortcut_reference_links: true,
408
409 implicit_figures: true,
411 inline_images: true,
412
413 tex_math_dollars: true,
415 tex_math_double_backslash: false,
416 tex_math_gfm: false,
417 tex_math_single_backslash: false,
418
419 footnotes: true,
421 inline_footnotes: true,
422
423 citations: true,
425
426 bracketed_spans: true,
428 native_spans: true,
429
430 mmd_title_block: false,
432 pandoc_title_block: true,
433 yaml_metadata_block: true,
434
435 markdown_in_html_blocks: false,
437 raw_attribute: true,
438 raw_html: true,
439 raw_tex: true,
440
441 all_symbols_escapable: true,
443 escaped_line_breaks: true,
444
445 alerts: false,
447 autolink_bare_uris: false,
448 emoji: false,
449 hard_line_breaks: false,
450 mark: false,
451 mmd_header_identifiers: false,
452 mmd_link_attributes: false,
453
454 bookdown_references: false,
456 bookdown_equation_references: false,
457 quarto_callouts: false,
458 quarto_crossrefs: false,
459 quarto_shortcodes: false,
460 }
461 }
462
463 fn quarto_defaults() -> Self {
464 let mut ext = Self::pandoc_defaults();
465
466 ext.executable_code = true;
467 ext.rmarkdown_inline_code = true;
468 ext.quarto_inline_code = true;
469 ext.quarto_callouts = true;
470 ext.quarto_crossrefs = true;
471 ext.quarto_shortcodes = true;
472
473 ext
474 }
475
476 fn rmarkdown_defaults() -> Self {
477 let mut ext = Self::pandoc_defaults();
478
479 ext.bookdown_references = true;
480 ext.bookdown_equation_references = true;
481 ext.executable_code = true;
482 ext.rmarkdown_inline_code = true;
483 ext.quarto_inline_code = false;
484 ext.tex_math_dollars = true;
485 ext.tex_math_single_backslash = true;
486
487 ext
488 }
489
490 fn gfm_defaults() -> Self {
491 let mut ext = Self::none_defaults();
492
493 ext.alerts = true;
494 ext.auto_identifiers = true;
495 ext.autolink_bare_uris = true;
496 ext.autolinks = true;
497 ext.backtick_code_blocks = true;
498 ext.emoji = true;
499 ext.fenced_code_blocks = true;
500 ext.footnotes = true;
501 ext.gfm_auto_identifiers = true;
502 ext.inline_links = true;
503 ext.pipe_tables = true;
504 ext.raw_html = true;
505 ext.strikeout = true;
506 ext.task_lists = true;
507 ext.tex_math_dollars = true;
508 ext.tex_math_gfm = true;
509 ext.yaml_metadata_block = true;
510
511 ext
512 }
513
514 fn commonmark_defaults() -> Self {
515 let mut ext = Self::none_defaults();
516 ext.autolinks = true;
526 ext.backtick_code_blocks = true;
527 ext.escaped_line_breaks = true;
528 ext.fenced_code_blocks = true;
529 ext.inline_images = true;
530 ext.inline_links = true;
531 ext.intraword_underscores = true;
532 ext.raw_html = true;
533 ext.reference_links = true;
534 ext.shortcut_reference_links = true;
535 ext
536 }
537
538 fn multimarkdown_defaults() -> Self {
539 let mut ext = Self::none_defaults();
540
541 ext.all_symbols_escapable = true;
542 ext.auto_identifiers = true;
543 ext.backtick_code_blocks = true;
544 ext.definition_lists = true;
545 ext.footnotes = true;
546 ext.implicit_figures = true;
547 ext.implicit_header_references = true;
548 ext.intraword_underscores = true;
549 ext.mmd_header_identifiers = true;
550 ext.mmd_link_attributes = true;
551 ext.mmd_title_block = true;
552 ext.pipe_tables = true;
553 ext.raw_attribute = true;
554 ext.raw_html = true;
555 ext.reference_links = true;
556 ext.shortcut_reference_links = true;
557 ext.subscript = true;
558 ext.superscript = true;
559 ext.tex_math_dollars = true;
560 ext.tex_math_double_backslash = true;
561
562 ext
563 }
564
565 pub fn merge_with_flavor(user_overrides: HashMap<String, bool>, flavor: Flavor) -> Self {
579 let defaults = Self::for_flavor(flavor);
580 Self::merge_overrides(defaults, user_overrides)
581 }
582
583 fn merge_overrides(mut base: Extensions, user_overrides: HashMap<String, bool>) -> Self {
584 for (key, value) in user_overrides {
585 let normalized_key = key.replace('_', "-");
586 match normalized_key.as_str() {
587 "blank-before-header" => base.blank_before_header = value,
588 "header-attributes" => base.header_attributes = value,
589 "auto-identifiers" => base.auto_identifiers = value,
590 "gfm-auto-identifiers" => base.gfm_auto_identifiers = value,
591 "implicit-header-references" => base.implicit_header_references = value,
592 "blank-before-blockquote" => base.blank_before_blockquote = value,
593 "fancy-lists" => base.fancy_lists = value,
594 "startnum" => base.startnum = value,
595 "example-lists" => base.example_lists = value,
596 "task-lists" => base.task_lists = value,
597 "definition-lists" => base.definition_lists = value,
598 "lists-without-preceding-blankline" => {
599 base.lists_without_preceding_blankline = value
600 }
601 "backtick-code-blocks" => base.backtick_code_blocks = value,
602 "fenced-code-blocks" => base.fenced_code_blocks = value,
603 "fenced-code-attributes" => base.fenced_code_attributes = value,
604 "executable-code" => base.executable_code = value,
605 "rmarkdown-inline-code" => base.rmarkdown_inline_code = value,
606 "quarto-inline-code" => base.quarto_inline_code = value,
607 "inline-code-attributes" => base.inline_code_attributes = value,
608 "simple-tables" => base.simple_tables = value,
609 "multiline-tables" => base.multiline_tables = value,
610 "grid-tables" => base.grid_tables = value,
611 "pipe-tables" => base.pipe_tables = value,
612 "table-captions" => base.table_captions = value,
613 "fenced-divs" => base.fenced_divs = value,
614 "native-divs" => base.native_divs = value,
615 "line-blocks" => base.line_blocks = value,
616 "intraword-underscores" => base.intraword_underscores = value,
617 "strikeout" => base.strikeout = value,
618 "superscript" => base.superscript = value,
619 "subscript" => base.subscript = value,
620 "inline-links" => base.inline_links = value,
621 "reference-links" => base.reference_links = value,
622 "shortcut-reference-links" => base.shortcut_reference_links = value,
623 "link-attributes" => base.link_attributes = value,
624 "autolinks" => base.autolinks = value,
625 "inline-images" => base.inline_images = value,
626 "implicit-figures" => base.implicit_figures = value,
627 "tex-math-dollars" => base.tex_math_dollars = value,
628 "tex-math-gfm" => base.tex_math_gfm = value,
629 "tex-math-single-backslash" => base.tex_math_single_backslash = value,
630 "tex-math-double-backslash" => base.tex_math_double_backslash = value,
631 "inline-footnotes" => base.inline_footnotes = value,
632 "footnotes" => base.footnotes = value,
633 "citations" => base.citations = value,
634 "bracketed-spans" => base.bracketed_spans = value,
635 "native-spans" => base.native_spans = value,
636 "yaml-metadata-block" => base.yaml_metadata_block = value,
637 "pandoc-title-block" => base.pandoc_title_block = value,
638 "mmd-title-block" => base.mmd_title_block = value,
639 "raw-html" => base.raw_html = value,
640 "markdown-in-html-blocks" => base.markdown_in_html_blocks = value,
641 "raw-tex" => base.raw_tex = value,
642 "raw-attribute" => base.raw_attribute = value,
643 "all-symbols-escapable" => base.all_symbols_escapable = value,
644 "escaped-line-breaks" => base.escaped_line_breaks = value,
645 "autolink-bare-uris" => base.autolink_bare_uris = value,
646 "hard-line-breaks" => base.hard_line_breaks = value,
647 "mmd-header-identifiers" => base.mmd_header_identifiers = value,
648 "mmd-link-attributes" => base.mmd_link_attributes = value,
649 "alerts" => base.alerts = value,
650 "emoji" => base.emoji = value,
651 "mark" => base.mark = value,
652 "quarto-callouts" => base.quarto_callouts = value,
653 "quarto-crossrefs" => base.quarto_crossrefs = value,
654 "quarto-shortcodes" => base.quarto_shortcodes = value,
655 "bookdown-references" => base.bookdown_references = value,
656 "bookdown-equation-references" => base.bookdown_equation_references = value,
657 _ => {}
658 }
659 }
660 base
661 }
662}
663
664#[cfg(test)]
665mod tests {
666 use super::{Extensions, Flavor};
667 use std::collections::HashMap;
668
669 #[test]
670 fn merge_with_flavor_keeps_known_extension_overrides() {
671 let mut overrides = HashMap::new();
672 overrides.insert("intraword-underscores".to_string(), false);
673 let ext = Extensions::merge_with_flavor(overrides, Flavor::Pandoc);
674 assert!(!ext.intraword_underscores);
675 }
676
677 #[test]
678 fn merge_with_flavor_ignores_unknown_extension_overrides() {
679 let mut overrides = HashMap::new();
680 overrides.insert("smart".to_string(), true);
681 overrides.insert("smart-quotes".to_string(), true);
682 let ext = Extensions::merge_with_flavor(overrides, Flavor::Gfm);
683 assert!(ext.strikeout, "known defaults should remain intact");
684 }
685
686 #[test]
687 fn lists_without_preceding_blankline_defaults_false_for_pandoc_and_gfm() {
688 assert!(!Extensions::for_flavor(Flavor::Pandoc).lists_without_preceding_blankline);
689 assert!(!Extensions::for_flavor(Flavor::Gfm).lists_without_preceding_blankline);
690 }
691
692 #[test]
693 fn merge_with_flavor_accepts_lists_without_preceding_blankline_override() {
694 let mut overrides = HashMap::new();
695 overrides.insert("lists-without-preceding-blankline".to_string(), true);
696 let ext = Extensions::merge_with_flavor(overrides, Flavor::Pandoc);
697 assert!(ext.lists_without_preceding_blankline);
698 }
699}
700
701#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
702#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
703pub enum PandocCompat {
704 #[cfg_attr(feature = "serde", serde(rename = "latest"))]
709 Latest,
710 #[cfg_attr(
712 feature = "serde",
713 serde(rename = "3.7", alias = "3-7", alias = "v3.7", alias = "v3-7")
714 )]
715 V3_7,
716 #[default]
718 #[cfg_attr(
719 feature = "serde",
720 serde(rename = "3.9", alias = "3-9", alias = "v3.9", alias = "v3-9")
721 )]
722 V3_9,
723}
724
725impl PandocCompat {
726 pub const PINNED_LATEST: Self = Self::V3_9;
728
729 pub fn effective(self) -> Self {
730 match self {
731 Self::Latest => Self::PINNED_LATEST,
732 other => other,
733 }
734 }
735}
736
737#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
748#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
749#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
750#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
751pub enum Dialect {
752 #[default]
755 Pandoc,
756 CommonMark,
758}
759
760impl Dialect {
761 pub fn for_flavor(flavor: Flavor) -> Self {
763 match flavor {
764 Flavor::CommonMark | Flavor::Gfm => Dialect::CommonMark,
765 Flavor::Pandoc | Flavor::Quarto | Flavor::RMarkdown | Flavor::MultiMarkdown => {
766 Dialect::Pandoc
767 }
768 }
769 }
770}
771
772#[derive(Debug, Clone)]
773#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
774#[cfg_attr(feature = "serde", serde(default, rename_all = "kebab-case"))]
775#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
776pub struct ParserOptions {
777 pub flavor: Flavor,
778 pub dialect: Dialect,
779 pub extensions: Extensions,
780 pub pandoc_compat: PandocCompat,
782 #[cfg_attr(feature = "serde", serde(skip))]
793 pub refdef_labels: Option<Arc<HashSet<String>>>,
794}
795
796impl Default for ParserOptions {
797 fn default() -> Self {
798 let flavor = Flavor::default();
799 Self {
800 flavor,
801 dialect: Dialect::for_flavor(flavor),
802 extensions: Extensions::for_flavor(flavor),
803 pandoc_compat: PandocCompat::default(),
804 refdef_labels: None,
805 }
806 }
807}
808
809impl ParserOptions {
810 pub fn effective_pandoc_compat(&self) -> PandocCompat {
811 self.pandoc_compat.effective()
812 }
813}
814
815#[cfg(feature = "schema")]
816impl schemars::JsonSchema for Flavor {
817 fn schema_name() -> std::borrow::Cow<'static, str> {
818 "Flavor".into()
819 }
820
821 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
822 schemars::json_schema!({
826 "type": "string",
827 "description": "Markdown flavor to parse and format against.",
828 "enum": [
829 "pandoc",
830 "quarto",
831 "rmarkdown",
832 "gfm",
833 "common-mark",
834 "commonmark",
835 "multimarkdown"
836 ]
837 })
838 }
839}
840
841#[cfg(feature = "schema")]
842impl schemars::JsonSchema for PandocCompat {
843 fn schema_name() -> std::borrow::Cow<'static, str> {
844 "PandocCompat".into()
845 }
846
847 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
848 schemars::json_schema!({
849 "type": "string",
850 "description": "Compatibility target for ambiguous Pandoc behavior.",
851 "enum": [
852 "latest",
853 "3.7", "3-7", "v3.7", "v3-7",
854 "3.9", "3-9", "v3.9", "v3-9"
855 ]
856 })
857 }
858}