This will be much more robust in the long haul, next up will be integrating into the build.rs script!
BA5Y6VSEHJQBOYBS6R6FE6IZDRNAPNIN5ITJXWK7L46RJVHNI7JAC
use pandoc::{OutputFormat, PandocOutput};
use pandoc_ast::{Block, Inline};
// Safely wrap i64 header levels in an enum
enum HeaderLevel {
H1,
H2,
H3,
H4,
H5,
H6,
}
// This is not TryFrom as there's not really much we can do to handle the error?
impl From<i64> for HeaderLevel {
fn from(value: i64) -> Self {
match value {
1 => HeaderLevel::H1,
2 => HeaderLevel::H2,
3 => HeaderLevel::H3,
4 => HeaderLevel::H4,
5 => HeaderLevel::H5,
6 => HeaderLevel::H6,
_ => panic!(
"Unexpected header level! Headers must be in range of 1 to 6 (inclusive), got: {}",
value
),
}
}
}
impl From<HeaderLevel> for &str {
fn from(value: HeaderLevel) -> Self {
match value {
HeaderLevel::H1 => "h1",
HeaderLevel::H2 => "h2",
HeaderLevel::H3 => "h3",
HeaderLevel::H4 => "h4",
HeaderLevel::H5 => "h5",
HeaderLevel::H6 => "h6",
}
}
}
struct ElementBlock<'a> {
name: &'a str,
expression: syn::Expr,
}
impl ElementBlock<'_> {
fn method_call(self) -> syn::Expr {
let mut args: Punctuated<syn::Expr, syn::token::Comma> = Punctuated::new();
args.push(self.expression);
let blocks: String = ast
.blocks
.iter()
.map(transform_block)
.collect::<Vec<String>>()
.join(", ");
dbg!(&blocks);
let file = syn::File {
shebang: None,
attrs: Vec::new(),
items: vec![syn::Item::Fn(syn::ItemFn {
attrs: Vec::new(),
vis: syn::Visibility::Public(syn::token::Pub::default()),
sig: syn::Signature {
constness: None,
asyncness: None,
unsafety: None,
abi: None,
fn_token: syn::token::Fn::default(),
ident: syn::Ident::new("test", proc_macro2::Span::call_site()),
generics: syn::Generics::default(),
paren_token: syn::token::Paren::default(),
inputs: Punctuated::new(),
variadic: None,
output: syn::ReturnType::Default,
},
block: Box::new(syn::Block {
brace_token: syn::token::Brace::default(),
stmts: vec![syn::Stmt::Expr(
syn::Expr::Tuple(syn::ExprTuple {
attrs: Vec::new(),
paren_token: syn::token::Paren::default(),
elems: Punctuated::from_iter(blocks.into_iter()),
}),
None,
)],
}),
})],
};
quote!(#file).to_string()
}
fn path_segment(segment: &str) -> syn::PathSegment {
syn::PathSegment {
ident: syn::Ident::new(segment, proc_macro2::Span::call_site()),
arguments: syn::PathArguments::None,
}
}
fn expr_path(name: &str) -> syn::Expr {
let mut segments: Punctuated<syn::PathSegment, syn::token::PathSep> = Punctuated::new();
blocks
// The path should be el::name
// e.g. el::h2
segments.push(path_segment("el"));
segments.push(path_segment(name));
let expr_path = syn::ExprPath {
attrs: Vec::new(),
qself: None,
path: syn::Path {
leading_colon: None,
segments,
},
};
syn::Expr::Path(expr_path)
fn transform_inlines(inlines: &Vec<Inline>) -> String {
let transformed: String = inlines.iter().map(transform_inline).collect();
dbg!(&transformed);
transformed
fn transform_inlines(inlines: &Vec<pandoc_ast::Inline>) -> syn::Expr {
let transformed: Vec<&str> = inlines.iter().map(transform_inline).collect();
let full_literal: String = transformed.join("");
dbg!(&full_literal);
// TODO: figure out what the span actually should be
let lit_str = syn::LitStr::new(&full_literal, proc_macro2::Span::call_site());
syn::Expr::Lit(syn::ExprLit {
attrs: Vec::new(),
lit: syn::Lit::Str(lit_str),
})
proc-macro2 = "1.0.69"
quote = "1.0.33"
syn = { version = "2.0.38", features = ["full", "extra-traits"] }