-
Notifications
You must be signed in to change notification settings - Fork 42
/
rmd.rs
92 lines (86 loc) · 3.08 KB
/
rmd.rs
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
use super::md;
use eyre::Result;
use stencila_schema::{
BlockContent, CodeBlock, CodeChunk, CodeExpression, CodeFragment, Delete, Emphasis,
InlineContent, Node, NontextualAnnotation, Paragraph, Strong, Subscript, Superscript,
};
/// Decode a R Markdown document to a `Node`
pub fn decode(input: &str) -> Result<Node> {
let mut node = md::decode(input)?;
if let Node::Article(article) = &mut node {
if let Some(content) = &mut article.content {
transform_blocks(content)
}
}
Ok(node)
}
fn transform_blocks(blocks: &mut Vec<BlockContent>) {
for block in blocks {
match block {
BlockContent::CodeBlock(CodeBlock {
programming_language,
text,
..
}) => {
let programming_language = programming_language
.clone()
.map(|boxed| *boxed)
.unwrap_or("".to_string());
if programming_language.starts_with("{r") && programming_language.ends_with("}") {
*block = BlockContent::CodeChunk(CodeChunk {
programming_language: "r".to_string(),
text: text.to_string(),
..Default::default()
})
}
}
BlockContent::Paragraph(Paragraph { content, .. }) => transform_inlines(content),
_ => (),
}
}
}
fn transform_inlines(inlines: &mut Vec<InlineContent>) {
for inline in inlines {
match inline {
// Code fragments prefixed with `r` get transformed to a CodeExpression
InlineContent::CodeFragment(CodeFragment { text, .. }) => {
if let Some(text) = text.strip_prefix("r ") {
*inline = InlineContent::CodeExpression(CodeExpression {
programming_language: "r".to_string(),
text: text.to_string(),
..Default::default()
})
}
}
// Recursively transform other inlines
InlineContent::Delete(Delete { content, .. })
| InlineContent::Emphasis(Emphasis { content, .. })
| InlineContent::Subscript(Subscript { content, .. })
| InlineContent::Superscript(Superscript { content, .. })
| InlineContent::Strong(Strong { content, .. })
| InlineContent::NontextualAnnotation(NontextualAnnotation { content, .. }) => {
transform_inlines(content)
}
_ => (),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::utils::tests::snapshot_content;
use insta::assert_json_snapshot;
#[ignore]
#[test]
fn rmd_articles() {
snapshot_content("articles/*.Rmd", |_path, content| {
assert_json_snapshot!(decode(&content).unwrap());
});
}
#[test]
fn rmd_fragments() {
snapshot_content("fragments/rmd/*.Rmd", |_path, content| {
assert_json_snapshot!(decode(&content).unwrap());
});
}
}