aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp A2020-01-03 16:43:21 +0100
committerPhilipp A2020-01-03 16:48:39 +0100
commit06e7d81088e33d7ee03e7088e1ec2289e9c2bf5c (patch)
tree59daa73de46abfdc60a6e3e4c11b43011ff49053
parent0f1a3e3578b934454a41a31eff15c23622719a67 (diff)
downloadrust-rst-0.3.1-renderer.tar.bz2
Added code block directivev0.3.1-rendererv0.3.1-parser
-rw-r--r--.editorconfig3
-rw-r--r--README.rst9
-rw-r--r--parser/Cargo.toml2
-rw-r--r--parser/src/conversion/block.rs19
-rw-r--r--parser/src/rst.pest32
-rw-r--r--parser/src/tests.rs35
-rw-r--r--renderer/Cargo.toml2
-rw-r--r--renderer/src/html.rs6
-rw-r--r--renderer/src/html/tests.rs19
9 files changed, 104 insertions, 23 deletions
diff --git a/.editorconfig b/.editorconfig
index d0e9252..c730fb1 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -8,3 +8,6 @@ end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = true
+
+[*.pest]
+indent_style = space
diff --git a/README.rst b/README.rst
index 9d8e3cb..d8a9f5d 100644
--- a/README.rst
+++ b/README.rst
@@ -10,7 +10,14 @@ RuSTructuredText |travis|
Designed around the `Docutils Document Tree`_ and the `reStructuredText specification`_,
this is supposed to become a library able to convert reStructuredText and Docutils XML to both each other and HTML5.
-Currently it can convert a subset of rST (e.g. this README) to HTML5.
+Currently it can convert a subset of rST (e.g. this README) to HTML5:
+
+.. code-block:: bash
+
+ cargo install rst
+ rst README.rst
+ # or
+ cargo run -- README.rst
This project is dual-licensed under Apache 2.0 and MIT.
diff --git a/parser/Cargo.toml b/parser/Cargo.toml
index 997cc35..a423fbe 100644
--- a/parser/Cargo.toml
+++ b/parser/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = 'rst_parser'
-version = '0.3.0'
+version = '0.3.1'
authors = ['Philipp A. <flying-sheep@web.de>']
edition = '2018'
description = 'a reStructuredText parser'
diff --git a/parser/src/conversion/block.rs b/parser/src/conversion/block.rs
index ab18c48..64aa33e 100644
--- a/parser/src/conversion/block.rs
+++ b/parser/src/conversion/block.rs
@@ -53,6 +53,7 @@ fn convert_body_elem(pair: Pair<Rule>) -> Result<c::BodyElement, Error> {
Rule::admonition_gen => convert_admonition_gen(pair)?.into(),
Rule::image => convert_image::<e::Image>(pair)?.into(),
Rule::bullet_list => convert_bullet_list(pair)?.into(),
+ Rule::code_directive => convert_code_directive(pair)?.into(),
rule => unimplemented!("unhandled rule {:?}", rule),
})
}
@@ -200,3 +201,21 @@ fn convert_bullet_item(pair: Pair<Rule>) -> Result<e::ListItem, Error> {
}
Ok(e::ListItem::with_children(children))
}
+
+fn convert_code_directive(pair: Pair<Rule>) -> Result<e::LiteralBlock, Error> {
+ let mut iter = pair.into_inner();
+ let (lang, code) = match (iter.next().unwrap(), iter.next()) {
+ (lang, Some(code)) => (Some(lang), code),
+ (code, None) => (None, code),
+ };
+ let children = code.into_inner().map(|l| match l.as_rule() {
+ Rule::code_line => l.as_str(),
+ Rule::code_line_blank => "\n",
+ _ => unreachable!(),
+ }.into()).collect();
+ let mut code_block = e::LiteralBlock::with_children(children);
+ if let Some(lang) = lang {
+ code_block.classes_mut().push(lang.as_str().to_owned());
+ };
+ Ok(code_block)
+}
diff --git a/parser/src/rst.pest b/parser/src/rst.pest
index f3a1516..18708c2 100644
--- a/parser/src/rst.pest
+++ b/parser/src/rst.pest
@@ -15,6 +15,7 @@ block = _{ PEEK[..] ~ hanging_block }
hanging_block = _{
substitution_def
| image_directive
+ | code_directive
| admonition
| admonition_gen
| target
@@ -24,17 +25,10 @@ hanging_block = _{
// TODO: implement all those things:
// | block_quote
// | verbatim
-// | image ✓
-// | code_block
// | doctest_block
-// | admonition ✓
-// | target ✓
// | horizontal_rule
-// | title ✓
// | table
// | ordered_list
-// | bullet_list ✓
-// | paragraph ✓
// | plain
}
@@ -86,9 +80,20 @@ image_opt_block = _{ PEEK[..-1] ~ PUSH(" " ~ POP) ~ image_option } //TODO: merg
image_option = { ":" ~ image_opt_name ~ ":" ~ line }
image_opt_name = { common_opt_name | "alt" | "height" | "width" | "scale" | "align" | "target" }
+// Code block. A directive
+
+code_directive = {
+ ".." ~ PUSH(" "+) ~ "code" ~ "-block"? ~ "::" ~ (" "+ ~ source)? ~ NEWLINE ~
+ blank_line+ ~ PEEK[..-1] ~ PUSH(" " ~ POP) ~ code_block ~ DROP
+}
+source = { (!NEWLINE ~ ANY)+ }
+code_block = { code_line ~ (code_line_blank* ~ PEEK[..] ~ code_line)* }
+code_line_blank = { " "* ~ NEWLINE }
+code_line = { (!NEWLINE ~ ANY)+ ~ NEWLINE }
+
// Admonition. A directive. The generic one has a title
-admonition = { ".." ~ PUSH(" "+) ~ ^"admonition::" ~ line ~ blank_line* ~ admonition_content? ~ DROP }
+admonition = { ".." ~ PUSH(" "+) ~ ^"admonition::" ~ line ~ blank_line* ~ admonition_content? ~ DROP }
admonition_gen = { ".." ~ PUSH(" "+) ~ admonition_type ~ "::" ~ (blank_line | line) ~ blank_line* ~ admonition_content? ~ DROP }
admonition_type = { ^"attention" | ^"caution" | ^"danger" | ^"error" | ^"hint" | ^"important" | ^"note" | ^"tip" | ^"warning" }
admonition_content = _{ PEEK[..-1] ~ PUSH(" " ~ POP) ~ hanging_block ~ block* } //TODO: merge with other directives?
@@ -272,11 +277,6 @@ marker = _{ (bullet_marker | "..") ~ " " }
-// code_block = {
-// ".. code" ~ "-block"? ~ ":: " ~ source ~ blank_line ~
-// NEWLINE ~ verbatim_chunk+
-// }
-
// doctest_block = { (doctest_line+ ~ (!(">" | blank_line) ~ line)*)+ }
// block_quote_raw = { ":" ~ blank_line ~ NEWLINE ~ nonblank_indented_line+ }
@@ -290,12 +290,6 @@ marker = _{ (bullet_marker | "..") ~ " " }
// block_quote = { block_quote_chunk+ }
-// nonblank_indented_line = { !blank_line ~ indented_line }
-
-// verbatim_chunk = { blank_line* ~ nonblank_indented_line+ }
-
-// verbatim = { verbatim_chunk+ }
-
// horizontal_rule = {
// ( "=" ~ sp ~ "=" ~ sp ~ "=" ~ (sp ~ "=")*
// | "-" ~ sp ~ "-" ~ sp ~ "-" ~ (sp ~ "-")*
diff --git a/parser/src/tests.rs b/parser/src/tests.rs
index 1ef965a..b4da633 100644
--- a/parser/src/tests.rs
+++ b/parser/src/tests.rs
@@ -136,6 +136,41 @@ fn admonitions() {
};
}
+#[allow(clippy::cognitive_complexity)]
+#[test]
+fn code() {
+ parses_to! {
+ parser: RstParser,
+ input: "\
+.. code::
+
+ Single line
+
+.. code-block:: python
+
+ print('x')
+
+ # second line
+
+The end
+",
+ rule: Rule::document,
+ tokens: [
+ code_directive(0, 26, [
+ code_block(14, 26, [ code_line(14, 26) ]),
+ ]),
+ code_directive(27, 83, [
+ source(43, 49),
+ code_block(54, 83, [
+ code_line(54, 65),
+ code_line_blank(65, 66),
+ code_line(69, 83),
+ ]),
+ ]),
+ paragraph(84, 91, [ str(84, 91) ]),
+ ]
+ };
+}
#[allow(clippy::cognitive_complexity)]
#[test]
diff --git a/renderer/Cargo.toml b/renderer/Cargo.toml
index d48dd34..c53c53f 100644
--- a/renderer/Cargo.toml
+++ b/renderer/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = 'rst_renderer'
-version = '0.3.0'
+version = '0.3.1'
authors = ['Philipp A. <flying-sheep@web.de>']
edition = '2018'
description = 'a reStructuredText renderer'
diff --git a/renderer/src/html.rs b/renderer/src/html.rs
index 73b994d..706ec2f 100644
--- a/renderer/src/html.rs
+++ b/renderer/src/html.rs
@@ -69,7 +69,11 @@ macro_rules! impl_html_render_simple {
impl HTMLRender for e::$type {
fn render_html<W>(&self, renderer: &mut HTMLRenderer<W>) -> Result<(), Error> where W: Write {
let multiple_children = self.children().len() > 1;
- write!(renderer.stream, "<{}>", stringify!($tag))?;
+ write!(renderer.stream, "<{}", stringify!($tag))?;
+ if self.classes().len() > 0 {
+ write!(renderer.stream, " class=\"{}\"", self.classes().join(" "))?;
+ }
+ write!(renderer.stream, ">")?;
if multiple_children { write!(renderer.stream, $post)?; }
for c in self.children() {
(*c).render_html(renderer)?;
diff --git a/renderer/src/html/tests.rs b/renderer/src/html/tests.rs
index 8477699..6a0f350 100644
--- a/renderer/src/html/tests.rs
+++ b/renderer/src/html/tests.rs
@@ -11,6 +11,7 @@ fn check_renders_to(rst: &str, expected: &str) {
render_html(&doc, &mut result_data, false).expect("Render error");
let result = String::from_utf8(result_data).expect("Could not decode");
assert_eq!(result.as_str().trim(), expected);
+ println!("{}", expected);
}
#[test]
@@ -222,6 +223,24 @@ fn test_table() {
}
*/
+#[test]
+fn code() {
+ check_renders_to("\
+.. code:: python
+
+ def foo():
+ print('Hi!')
+
+ # comment
+", "\
+<pre class=\"python\">def foo():
+ print('Hi!')
+
+ # comment
+</pre>\
+");
+}
+
/*
#[test]
fn test_field_list() {