1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
use std::path::PathBuf;
pub fn pandoc_stringify(inlines: &[pandoc_ast::Inline]) -> String {
fn pandoc_stringify_(result: &mut String, inlines: &[pandoc_ast::Inline]) {
for inline in inlines {
match inline {
pandoc_ast::Inline::Str(s)
| pandoc_ast::Inline::Code(_, s)
| pandoc_ast::Inline::Math(_, s) => result.push_str(s),
pandoc_ast::Inline::Emph(inner)
| pandoc_ast::Inline::Underline(inner)
| pandoc_ast::Inline::Strong(inner)
| pandoc_ast::Inline::Strikeout(inner)
| pandoc_ast::Inline::Superscript(inner)
| pandoc_ast::Inline::Subscript(inner)
| pandoc_ast::Inline::SmallCaps(inner)
| pandoc_ast::Inline::Quoted(_, inner)
| pandoc_ast::Inline::Cite(_, inner)
| pandoc_ast::Inline::Link(_, inner, _)
| pandoc_ast::Inline::Image(_, inner, _)
| pandoc_ast::Inline::Span(_, inner) => pandoc_stringify_(result, inner),
pandoc_ast::Inline::Space => result.push(' '),
pandoc_ast::Inline::SoftBreak => todo!(),
pandoc_ast::Inline::LineBreak => todo!(),
pandoc_ast::Inline::RawInline(_, _) => todo!(),
pandoc_ast::Inline::Note(_) => todo!(),
}
}
}
let mut result = String::new();
pandoc_stringify_(&mut result, inlines);
result
}
/// Follows the algorithm specified in the Pandoc manual[1]
///
/// [1]: <https://pandoc.org/MANUAL.html#extension-auto_identifiers>
#[derive(Debug)]
pub struct AutoIdentifier(pub String);
impl std::ops::Deref for AutoIdentifier {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<AutoIdentifier> for String {
fn from(id: AutoIdentifier) -> Self {
id.0
}
}
impl From<&[pandoc_ast::Inline]> for AutoIdentifier {
fn from(inlines: &[pandoc_ast::Inline]) -> Self {
let text = pandoc_stringify(inlines);
AutoIdentifier::from(text.as_str())
}
}
impl From<&str> for AutoIdentifier {
fn from(text: &str) -> Self {
let id = text
.chars()
.skip_while(|ch| !ch.is_alphabetic())
.filter_map(|ch| {
if !ch.is_ascii_alphanumeric()
&& !ch.is_whitespace()
&& ch != '_'
&& ch != '-'
&& ch != '.'
{
return None;
}
if ch.is_whitespace() {
return Some('-');
}
Some(ch.to_ascii_lowercase())
})
.collect();
AutoIdentifier(id)
}
}
pub trait PandocOutputExt {
fn buffer(self) -> String;
fn file(self) -> PathBuf;
}
impl PandocOutputExt for pandoc::PandocOutput {
fn buffer(self) -> String {
match self {
pandoc::PandocOutput::ToBuffer(buffer) => buffer,
pandoc::PandocOutput::ToBufferRaw(_) => {
panic!("Expected text pandoc output, found binary format")
}
pandoc::PandocOutput::ToFile(_) => {
panic!("Expected buffered pandoc output, found file")
}
}
}
fn file(self) -> PathBuf {
match self {
pandoc::PandocOutput::ToFile(file) => file,
_ => panic!("Expected file pandoc output, found buffer"),
}
}
}
pub type PandocMeta = pandoc_ast::Map<String, pandoc_ast::MetaValue>;
|