diff --git a/Cargo.toml b/Cargo.toml index 8a53c928..45bfd139 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ serde = { version = "1", features = ["derive"], optional = true } env_logger = "0.11" criterion = "0.5" pretty_assertions = "1" +serde_json = { version = "1" } swc_core = { version = "0.100", features = [ "ecma_ast", "ecma_visit", diff --git a/readme.md b/readme.md index ad24a61f..acf4e9b0 100644 --- a/readme.md +++ b/readme.md @@ -264,6 +264,9 @@ The following bash scripts are useful when working on this project: ```sh RUST_BACKTRACE=1 cargo test ``` + ```sh + RUST_BACKTRACE=1 cargo test --features json + ``` * docs: ```sh cargo doc --document-private-items diff --git a/src/mdast.rs b/src/mdast.rs index 1a9e0ee3..580df4b2 100644 --- a/src/mdast.rs +++ b/src/mdast.rs @@ -86,7 +86,7 @@ pub enum AlignKind { #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "type") + serde(tag = "type", rename_all = "camelCase") )] pub enum Node { // Document: @@ -448,7 +448,7 @@ impl Node { #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "mdxJsxExpressionAttribute") + serde(untagged, rename = "mdxJsxExpressionAttribute") )] pub enum AttributeContent { /// JSX expression. @@ -483,7 +483,7 @@ pub struct AttributeValueExpression { #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "type") + serde(untagged) )] pub enum AttributeValue { /// Expression value. @@ -499,7 +499,6 @@ pub enum AttributeValue { /// > | /// ^^^ /// ``` - #[cfg_attr(feature = "serde", serde(rename = "literal"))] Literal(String), } @@ -510,11 +509,7 @@ pub enum AttributeValue { /// ^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "root") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Root { // Parent. /// Content model. @@ -530,11 +525,7 @@ pub struct Root { /// ^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "paragraph") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Paragraph { // Parent. /// Content model. @@ -550,11 +541,7 @@ pub struct Paragraph { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "heading") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Heading { // Parent. /// Content model. @@ -573,11 +560,7 @@ pub struct Heading { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "thematicBreak") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ThematicBreak { // Void. /// Positional info. @@ -591,11 +574,7 @@ pub struct ThematicBreak { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "blockquote") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BlockQuote { // Parent. /// Content model. @@ -611,11 +590,7 @@ pub struct BlockQuote { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "list") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct List { // Parent. /// Content model. @@ -640,11 +615,7 @@ pub struct List { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "listItem") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ListItem { // Parent. /// Content model. @@ -667,11 +638,7 @@ pub struct ListItem { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "html") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Html { // Text. /// Content model. @@ -691,11 +658,7 @@ pub struct Html { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "code") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Code { // Text. /// Content model. @@ -720,11 +683,7 @@ pub struct Code { /// ^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "math") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Math { // Text. /// Content model. @@ -743,11 +702,7 @@ pub struct Math { /// ^^^^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "definition") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Definition { // Void. /// Positional info. @@ -780,11 +735,7 @@ pub struct Definition { /// ^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "text") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Text { // Text. /// Content model. @@ -800,11 +751,7 @@ pub struct Text { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "emphasis") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Emphasis { // Parent. /// Content model. @@ -820,11 +767,7 @@ pub struct Emphasis { /// ^^^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "strong") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Strong { // Parent. /// Content model. @@ -840,11 +783,7 @@ pub struct Strong { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "inlineCode") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct InlineCode { // Text. /// Content model. @@ -860,11 +799,7 @@ pub struct InlineCode { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "inlineMath") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct InlineMath { // Text. /// Content model. @@ -881,11 +816,7 @@ pub struct InlineMath { /// | b /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "break") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Break { // Void. /// Positional info. @@ -899,11 +830,7 @@ pub struct Break { /// ^^^^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "link") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Link { // Parent. /// Content model. @@ -925,11 +852,7 @@ pub struct Link { /// ^^^^^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "image") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Image { // Void. /// Positional info. @@ -953,11 +876,7 @@ pub struct Image { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "linkReference") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct LinkReference { // Parent. /// Content model. @@ -990,11 +909,7 @@ pub struct LinkReference { /// ^^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "imageReference") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ImageReference { // Void. /// Positional info. @@ -1029,11 +944,7 @@ pub struct ImageReference { /// ^^^^^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "footnoteDefinition") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FootnoteDefinition { // Parent. /// Content model. @@ -1062,11 +973,7 @@ pub struct FootnoteDefinition { /// ^^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "footnoteReference") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FootnoteReference { // Void. /// Positional info. @@ -1095,11 +1002,7 @@ pub struct FootnoteReference { /// ^^^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "table") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Table { // Parent. /// Content model. @@ -1118,11 +1021,7 @@ pub struct Table { /// ^^^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "tableRow") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TableRow { // Parent. /// Content model. @@ -1138,11 +1037,7 @@ pub struct TableRow { /// ^^^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "tableCell") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TableCell { // Parent. /// Content model. @@ -1158,11 +1053,7 @@ pub struct TableCell { /// ^^^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "delete") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Delete { // Parent. /// Content model. @@ -1182,11 +1073,7 @@ pub struct Delete { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "yaml") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Yaml { // Void. /// Content model. @@ -1206,11 +1093,7 @@ pub struct Yaml { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "toml") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Toml { // Void. /// Content model. @@ -1226,11 +1109,7 @@ pub struct Toml { /// ^^^^^^^^^^^^^^^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "mdxjsEsm") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct MdxjsEsm { // Literal. /// Content model. @@ -1249,11 +1128,7 @@ pub struct MdxjsEsm { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "mdxFlowExpression") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct MdxFlowExpression { // Literal. /// Content model. @@ -1272,11 +1147,7 @@ pub struct MdxFlowExpression { /// ^^^ /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "mdxTextExpression") -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct MdxTextExpression { // Literal. /// Content model. @@ -1298,7 +1169,7 @@ pub struct MdxTextExpression { #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "mdxJsxFlowElement") + serde(rename_all = "camelCase") )] pub struct MdxJsxFlowElement { // Parent. @@ -1325,7 +1196,7 @@ pub struct MdxJsxFlowElement { #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), - serde(tag = "type", rename = "mdxJsxTextElement") + serde(rename_all = "camelCase") )] pub struct MdxJsxTextElement { // Parent. diff --git a/tests/serde.rs b/tests/serde.rs new file mode 100644 index 00000000..243a98d3 --- /dev/null +++ b/tests/serde.rs @@ -0,0 +1,117 @@ +use markdown::mdast::Node; +use markdown::message::Message; + +#[allow(unused)] +#[derive(Debug)] +enum Error { + Mdast(Message), + Serde(serde_json::Error), +} + +#[cfg_attr(feature = "serde", test)] +fn serde() -> Result<(), Error> { + let source = markdown::to_mdast( + r#" +--- +title: Serde +--- + +import Test from 'test'; +import Inner from 'test'; +import {Another, YetAnother} from 'another'; + +# , {username}! + +> Blockquote +Add test constructs below! + +## Test serialization and deserialization of mdast + + + + ## Inner + [Link](./link.md) + + + + + +{test} this is text expression + + + +# Text + +~~The world is flat.~~ We now know that the world is round. + +*Emphasis* + +*Strong Emphasis* + +$This is math$ + +Let's break\ +yes! + +*** + +## List + +* item1 +* item2 +* item3 + +## Code block + +```shell +cargo test --features json +``` + +## Inline + +`Inline code` with backticks + +## Image + +![Image](http://url/a.png) + +## Table + +| Syntax | Description | +|-----------|-------------| +| Header | Title | +| Paragraph | Text | + +## Task lists + +- [x] Write the press release +- [ ] Update the website +- [ ] Contact the media + +## Footnotes + +Here's a simple footnote,[^1] and here's a longer one.[^bignote] + +[^1]: This is the first footnote. + +[^bignote]: Here's one with multiple paragraphs and code. + + Indent paragraphs to include them in the footnote. + + `{ my code }` + + Add as many paragraphs as you like. + +"#, + &markdown::ParseOptions::mdx(), + ) + .map_err(Error::Mdast)?; + + let value: String = serde_json::to_string(&source).map_err(Error::Serde)?; + + let target: Node = serde_json::from_slice(value.as_bytes()).map_err(Error::Serde)?; + + pretty_assertions::assert_eq!(source, target); + + Ok(()) +}