extern crate serde_json;
#[macro_use]
extern crate serde_derive;
mod visitor;
use serde_json::{from_str, to_string};
pub use std::collections::BTreeMap as Map;
pub use visitor::*;
pub type Int = i64;
pub type Double = f64;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct Pandoc {
pub meta: Map<String, MetaValue>,
pub blocks: Vec<Block>,
#[serde(rename = "pandoc-api-version")]
pub pandoc_api_version: Vec<u32>,
}
impl Pandoc {
fn from_json(json: &str) -> Self {
let v: serde_json::Value = from_str(json).unwrap();
let obj = v.as_object().expect("broken pandoc json");
assert!(obj.contains_key("pandoc-api-version"), "Please update your pandoc to at least version 1.18 or use an older version of `pandoc-ast`");
let s = serde_json::to_string_pretty(&v).unwrap();
let data: Self = match from_str(&s) {
Ok(data) => data,
Err(err) => panic!("json is not in the pandoc format: {:?}\n{}", err, s),
};
assert_eq!(
data.pandoc_api_version[0], 1,
"pandoc-ast minor version mismatch: \
please file a bug report against `pandoc-ast` to update for the newest pandoc version"
);
assert!(
(20..23).contains(&data.pandoc_api_version[1]),
"pandoc-ast minor version mismatch: \
please file a bug report against `pandoc-ast` to update for the newest pandoc version"
);
data
}
fn to_json(&self) -> String {
to_string(self).expect("serialization failed")
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(tag = "t", content = "c")]
pub enum MetaValue {
MetaMap(Map<String, Box<MetaValue>>),
MetaList(Vec<MetaValue>),
MetaBool(bool),
MetaString(String),
MetaInlines(Vec<Inline>),
MetaBlocks(Vec<Block>),
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(tag = "t", content = "c")]
pub enum Block {
Plain(Vec<Inline>),
Para(Vec<Inline>),
LineBlock(Vec<Vec<Inline>>),
CodeBlock(Attr, String),
RawBlock(Format, String),
BlockQuote(Vec<Block>),
OrderedList(ListAttributes, Vec<Vec<Block>>),
BulletList(Vec<Vec<Block>>),
DefinitionList(Vec<(Vec<Inline>, Vec<Vec<Block>>)>),
Header(Int, Attr, Vec<Inline>),
HorizontalRule,
Table(
Attr,
Caption,
Vec<ColSpec>,
TableHead,
Vec<TableBody>,
TableFoot
),
Div(Attr, Vec<Block>),
Null,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(tag = "t", content = "c")]
pub enum Inline {
Str(String),
Emph(Vec<Inline>),
Underline(Vec<Inline>),
Strong(Vec<Inline>),
Strikeout(Vec<Inline>),
Superscript(Vec<Inline>),
Subscript(Vec<Inline>),
SmallCaps(Vec<Inline>),
Quoted(QuoteType, Vec<Inline>),
Cite(Vec<Citation>, Vec<Inline>),
Code(Attr, String),
Space,
SoftBreak,
LineBreak,
Math(MathType, String),
RawInline(Format, String),
Link(Attr, Vec<Inline>, Target),
Image(Attr, Vec<Inline>, Target),
Note(Vec<Block>),
Span(Attr, Vec<Inline>),
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[serde(tag = "t")]
pub enum Alignment {
AlignLeft,
AlignRight,
AlignCenter,
AlignDefault,
}
pub type ListAttributes = (Int, ListNumberStyle, ListNumberDelim);
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[serde(tag = "t")]
pub enum ListNumberStyle {
DefaultStyle,
Example,
Decimal,
LowerRoman,
UpperRoman,
LowerAlpha,
UpperAlpha,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[serde(tag = "t")]
pub enum ListNumberDelim {
DefaultDelim,
Period,
OneParen,
TwoParens,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
pub struct Format(pub String);
pub type Attr = (String, Vec<String>, Vec<(String, String)>);
pub type TableCell = Vec<Block>;
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[serde(tag = "t")]
pub enum QuoteType {
SingleQuote,
DoubleQuote,
}
pub type Caption = (Option<ShortCaption>, Vec<Block>);
pub type ShortCaption = Vec<Inline>;
pub type RowHeadColumns = Int;
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)]
#[serde(tag = "t")]
pub enum ColWidth {
ColWidth(Double),
ColWidthDefault
}
pub type ColSpec = (Alignment, ColWidth);
pub type Row = (Attr, Vec<Cell>);
pub type TableHead = (Attr, Vec<Row>);
pub type TableBody = (Attr, RowHeadColumns, Vec<Row>, Vec<Row>);
pub type TableFoot = (Attr, Vec<Row>);
pub type Cell = (Attr, Alignment, RowSpan, ColSpan, Vec<Block>);
pub type RowSpan = Int;
pub type ColSpan = Int;
pub type Target = (String, String);
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[serde(tag = "t")]
pub enum MathType {
DisplayMath,
InlineMath,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[allow(non_snake_case)]
pub struct Citation {
pub citationId: String,
pub citationPrefix: Vec<Inline>,
pub citationSuffix: Vec<Inline>,
pub citationMode: CitationMode,
pub citationNoteNum: Int,
pub citationHash: Int,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[serde(tag = "t")]
pub enum CitationMode {
AuthorInText,
SuppressAuthor,
NormalCitation,
}
pub fn filter<F: FnOnce(Pandoc) -> Pandoc>(json: String, f: F) -> String {
f(Pandoc::from_json(&json)).to_json()
}