diff options
| author | Philipp A | 2020-01-03 16:43:21 +0100 | 
|---|---|---|
| committer | Philipp A | 2020-01-03 16:48:39 +0100 | 
| commit | 06e7d81088e33d7ee03e7088e1ec2289e9c2bf5c (patch) | |
| tree | 59daa73de46abfdc60a6e3e4c11b43011ff49053 | |
| parent | 0f1a3e3578b934454a41a31eff15c23622719a67 (diff) | |
| download | rust-rst-0.3.1-parser.tar.bz2 | |
Added code block directivev0.3.1-rendererv0.3.1-parser
| -rw-r--r-- | .editorconfig | 3 | ||||
| -rw-r--r-- | README.rst | 9 | ||||
| -rw-r--r-- | parser/Cargo.toml | 2 | ||||
| -rw-r--r-- | parser/src/conversion/block.rs | 19 | ||||
| -rw-r--r-- | parser/src/rst.pest | 32 | ||||
| -rw-r--r-- | parser/src/tests.rs | 35 | ||||
| -rw-r--r-- | renderer/Cargo.toml | 2 | ||||
| -rw-r--r-- | renderer/src/html.rs | 6 | ||||
| -rw-r--r-- | renderer/src/html/tests.rs | 19 | 
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 @@ -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() { | 
