Skip to content

Commit 4488211

Browse files
authored
future-proof enums
Add variants and attributes to future-proof enums. My guiding principles were: 1. enums that reflect markdown should be exhaustive, since we can assume a fairly stable markdown spec 2. enums that reflect mdq-specific inputs or non-markdown outputs (specifically, errors) should be non-exhaustive, so that mdq can add new features without breaking the API Resolves #377. See that ticket for an analysis of the enums currently in the code base. ## Breaking changes - add `FrontMatterVariant::Json` variant - change `FrontMatterVariant::separator()`'s signature to reflect that Json doesn't have a separator line. - add various `#[non_exhaustive]` attributes
1 parent 7506347 commit 4488211

File tree

6 files changed

+75
-21
lines changed

6 files changed

+75
-21
lines changed

src/md_elem/tree.rs

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -493,8 +493,40 @@ pub mod elem {
493493

494494
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
495495
pub enum FrontMatterVariant {
496+
/// ```markdown
497+
/// +++
498+
/// front = 'matter'
499+
/// +++
500+
/// ```
496501
Toml,
502+
503+
/// ```markdown
504+
/// ---
505+
/// front: matter
506+
/// ---
507+
/// ```
497508
Yaml,
509+
510+
/// ```markdown
511+
/// {
512+
/// "front": "matter"
513+
/// }
514+
/// ```
515+
///
516+
/// The [`FrontMatter::body`] for a `FrontMatter` of this variant will be the entire JSON text, including the
517+
/// opening and closing braces. This means you should not print any surrounding prefix or suffix delimiter
518+
/// lines when rendering front matter of this variant, unlike the other variants. The body will _not_ include
519+
/// a trailing newline after the last closing brace.
520+
///
521+
/// <div class="warning">
522+
///
523+
/// mdq does not currently support parsing JSON front matter. This enum variant is provided for completeness
524+
/// and future-proofing. API consumers should still account for it (and may create [`MdElem::FrontMatter`] nodes
525+
/// with it); just be aware that [`MdDoc::parse`] will not produce any front matter nodes with this variant
526+
/// as of this version.
527+
///
528+
/// </div>
529+
Json,
498530
}
499531

500532
impl FrontMatterVariant {
@@ -510,21 +542,26 @@ pub mod elem {
510542
match self {
511543
FrontMatterVariant::Toml => "toml",
512544
FrontMatterVariant::Yaml => "yaml",
545+
FrontMatterVariant::Json => "json",
513546
}
514547
}
515548

516-
/// Gets the separator that's used in front matter syntax to specify this variant.
549+
/// Gets the separator used in front matter syntax to specify this variant.
550+
///
551+
/// JSON has no such separator; see [`FrontMatterVariant::Json`].
517552
///
518553
/// ```
519554
/// use mdq::md_elem::elem::FrontMatterVariant;
520555
///
521-
/// assert_eq!(FrontMatterVariant::Toml.separator(), "+++");
522-
/// assert_eq!(FrontMatterVariant::Yaml.separator(), "---");
556+
/// assert_eq!(FrontMatterVariant::Toml.separator(), Some("+++"));
557+
/// assert_eq!(FrontMatterVariant::Yaml.separator(), Some("---"));
558+
/// assert_eq!(FrontMatterVariant::Json.separator(), None);
523559
/// ```
524-
pub fn separator(self) -> &'static str {
560+
pub fn separator(self) -> Option<&'static str> {
525561
match self {
526-
FrontMatterVariant::Toml => "+++",
527-
FrontMatterVariant::Yaml => "---",
562+
FrontMatterVariant::Toml => Some("+++"),
563+
FrontMatterVariant::Yaml => Some("---"),
564+
FrontMatterVariant::Json => None,
528565
}
529566
}
530567
}
@@ -860,7 +897,7 @@ pub mod elem {
860897
pub item: Vec<MdElem>,
861898
}
862899

863-
/// ~~deleted~~, _emphasized_, or **strong**; see [`Span`]
900+
/// ~~deleted (strikethrough)~~, _emphasized_, or **strong**; see [`Span`]
864901
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
865902
pub enum SpanVariant {
866903
Delete,

src/output/fmt_md.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub struct MdWriterOptions {
5555

5656
/// Whether to put link definitions at the end of each section, or at the bottom of the whole document.
5757
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default, ValueEnum)]
58+
#[non_exhaustive]
5859
pub enum ReferencePlacement {
5960
/// Show link definitions in the first section that uses the link.
6061
///
@@ -402,11 +403,15 @@ impl<'md> MdWriterState<'_, 'md> {
402403

403404
fn write_front_matter<W: SimpleWrite>(&mut self, out: &mut Output<W>, front_matter: &'md FrontMatter) {
404405
out.with_pre_block(|out| {
405-
out.write_str(front_matter.variant.separator());
406-
out.write_char('\n');
406+
if let Some(sep) = front_matter.variant.separator() {
407+
out.write_str(sep);
408+
out.write_char('\n');
409+
}
407410
out.write_str(&front_matter.body);
408-
out.write_char('\n');
409-
out.write_str(front_matter.variant.separator());
411+
if let Some(sep) = front_matter.variant.separator() {
412+
out.write_char('\n');
413+
out.write_str(sep);
414+
}
410415
})
411416
}
412417

@@ -582,6 +587,7 @@ pub(crate) mod tests {
582587
CodeBlock(CodeBlock{variant: CodeVariant::Math{metadata: Some(_)}, ..}),
583588
FrontMatter(FrontMatter{variant: FrontMatterVariant::Toml, ..}),
584589
FrontMatter(FrontMatter{variant: FrontMatterVariant::Yaml, ..}),
590+
FrontMatter(FrontMatter{variant: FrontMatterVariant::Json, ..}),
585591
Paragraph(_),
586592
BlockQuote(_),
587593
List(_),
@@ -1394,6 +1400,20 @@ pub(crate) mod tests {
13941400
+++"#},
13951401
);
13961402
}
1403+
1404+
#[test]
1405+
fn json() {
1406+
check_render(
1407+
md_elems![FrontMatter {
1408+
variant: FrontMatterVariant::Json,
1409+
body: "{\n 'one': 'two'\n}".replace('\'', "\"").to_string(),
1410+
}],
1411+
indoc! {r#"
1412+
{
1413+
"one": "two"
1414+
}"#},
1415+
);
1416+
}
13971417
}
13981418

13991419
mod inline {

src/output/link_transform.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::ops::Deref;
1010

1111
/// Whether to render links as inline, reference form, or keep them as they were.
1212
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default, ValueEnum)]
13+
#[non_exhaustive]
1314
pub enum LinkTransform {
1415
/// Keep links as they were in the original
1516
Keep,

src/output/tree_ref_serde.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -212,16 +212,10 @@ impl<'md> SerdeElem<'md> {
212212
language,
213213
}
214214
}
215-
MdElem::FrontMatter(fm) => {
216-
let variant = match fm.variant {
217-
FrontMatterVariant::Yaml => "yaml",
218-
FrontMatterVariant::Toml => "toml",
219-
};
220-
Self::FrontMatter {
221-
variant,
222-
body: &fm.body,
223-
}
224-
}
215+
MdElem::FrontMatter(fm) => Self::FrontMatter {
216+
variant: fm.variant.name(),
217+
body: &fm.body,
218+
},
225219
MdElem::Inline(Inline::Link(link)) => match link {
226220
crate::md_elem::elem::Link::Standard(standard_link) => Self::Link {
227221
display: inlines_to_string(&standard_link.display, inlines_writer),

src/run/cli.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ impl CliOptions {
240240

241241
/// Output formats, analogous to `--output` in the CLI.
242242
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, ValueEnum)]
243+
#[non_exhaustive]
243244
pub enum OutputFormat {
244245
/// Output results as Markdown.
245246
Markdown,

src/run/run_main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::io::Write;
1212

1313
/// The run's overall possible error.
1414
#[derive(Debug)]
15+
#[non_exhaustive]
1516
pub enum Error {
1617
/// User provided an invalid selector string.
1718
///

0 commit comments

Comments
 (0)