mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-08 11:18:48 +00:00
156 lines
4.8 KiB
Rust
156 lines
4.8 KiB
Rust
//! Removes markdown from strings.
|
|
use pulldown_cmark::{Event, Parser, Tag};
|
|
|
|
/// Removes all markdown, keeping the text and code blocks
|
|
///
|
|
/// Currently limited in styling, i.e. no ascii tables or lists
|
|
pub(crate) fn remove_markdown(markdown: &str) -> String {
|
|
let mut out = String::new();
|
|
let parser = Parser::new(markdown);
|
|
|
|
for event in parser {
|
|
match event {
|
|
Event::Text(text) | Event::Code(text) => out.push_str(&text),
|
|
Event::SoftBreak => out.push(' '),
|
|
Event::HardBreak | Event::Rule | Event::End(Tag::CodeBlock(_)) => out.push('\n'),
|
|
Event::End(Tag::Paragraph) => {
|
|
out.push('\n');
|
|
out.push('\n');
|
|
}
|
|
Event::Start(_)
|
|
| Event::End(_)
|
|
| Event::Html(_)
|
|
| Event::FootnoteReference(_)
|
|
| Event::TaskListMarker(_) => (),
|
|
}
|
|
}
|
|
|
|
if let Some(p) = out.rfind(|c| c != '\n') {
|
|
out.drain(p + 1..);
|
|
}
|
|
|
|
out
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use expect_test::expect;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn smoke_test() {
|
|
let res = remove_markdown(
|
|
r##"
|
|
A function or function pointer.
|
|
|
|
Functions are the primary way code is executed within Rust. Function blocks, usually just
|
|
called functions, can be defined in a variety of different places and be assigned many
|
|
different attributes and modifiers.
|
|
|
|
Standalone functions that just sit within a module not attached to anything else are common,
|
|
but most functions will end up being inside [`impl`] blocks, either on another type itself, or
|
|
as a trait impl for that type.
|
|
|
|
```rust
|
|
fn standalone_function() {
|
|
// code
|
|
}
|
|
|
|
pub fn public_thing(argument: bool) -> String {
|
|
// code
|
|
# "".to_string()
|
|
}
|
|
|
|
struct Thing {
|
|
foo: i32,
|
|
}
|
|
|
|
impl Thing {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
foo: 42,
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
In addition to presenting fixed types in the form of `fn name(arg: type, ..) -> return_type`,
|
|
functions can also declare a list of type parameters along with trait bounds that they fall
|
|
into.
|
|
|
|
```rust
|
|
fn generic_function<T: Clone>(x: T) -> (T, T, T) {
|
|
(x.clone(), x.clone(), x.clone())
|
|
}
|
|
|
|
fn generic_where<T>(x: T) -> T
|
|
where T: std::ops::Add<Output = T> + Copy
|
|
{
|
|
x + x + x
|
|
}
|
|
```
|
|
|
|
Declaring trait bounds in the angle brackets is functionally identical to using a `where`
|
|
clause. It's up to the programmer to decide which works better in each situation, but `where`
|
|
tends to be better when things get longer than one line.
|
|
|
|
Along with being made public via `pub`, `fn` can also have an [`extern`] added for use in
|
|
FFI.
|
|
|
|
For more information on the various types of functions and how they're used, consult the [Rust
|
|
book] or the [Reference].
|
|
|
|
[`impl`]: keyword.impl.html
|
|
[`extern`]: keyword.extern.html
|
|
[Rust book]: ../book/ch03-03-how-functions-work.html
|
|
[Reference]: ../reference/items/functions.html
|
|
"##,
|
|
);
|
|
expect![[r#"
|
|
A function or function pointer.
|
|
|
|
Functions are the primary way code is executed within Rust. Function blocks, usually just called functions, can be defined in a variety of different places and be assigned many different attributes and modifiers.
|
|
|
|
Standalone functions that just sit within a module not attached to anything else are common, but most functions will end up being inside impl blocks, either on another type itself, or as a trait impl for that type.
|
|
|
|
fn standalone_function() {
|
|
// code
|
|
}
|
|
|
|
pub fn public_thing(argument: bool) -> String {
|
|
// code
|
|
# "".to_string()
|
|
}
|
|
|
|
struct Thing {
|
|
foo: i32,
|
|
}
|
|
|
|
impl Thing {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
foo: 42,
|
|
}
|
|
}
|
|
}
|
|
|
|
In addition to presenting fixed types in the form of fn name(arg: type, ..) -> return_type, functions can also declare a list of type parameters along with trait bounds that they fall into.
|
|
|
|
fn generic_function<T: Clone>(x: T) -> (T, T, T) {
|
|
(x.clone(), x.clone(), x.clone())
|
|
}
|
|
|
|
fn generic_where<T>(x: T) -> T
|
|
where T: std::ops::Add<Output = T> + Copy
|
|
{
|
|
x + x + x
|
|
}
|
|
|
|
Declaring trait bounds in the angle brackets is functionally identical to using a where clause. It's up to the programmer to decide which works better in each situation, but where tends to be better when things get longer than one line.
|
|
|
|
Along with being made public via pub, fn can also have an extern added for use in FFI.
|
|
|
|
For more information on the various types of functions and how they're used, consult the Rust book or the Reference."#]].assert_eq(&res);
|
|
}
|
|
}
|