All formats

rtf-parser

LanguageRust
LicenseMIT
Repositorygithub.com/d0rianb/rtf-parser
Documentationdocs.rs/rtf-parser
Depends onserde (optional wasm-bindgen and tsify for the WebAssembly build)
Read / writereads RTF; doesn't write RTF

rtf-parser has two stages. Lexer::scan turns RTF text into a Vec<Token> (control words, groups, plain text), and Parser::new(tokens).parse() builds an RtfDocument:

It implements RTF 1.9 with UTF-16 \uN escapes and special characters (dashes, quotes). Known gaps: \bin binary data isn’t supported and can break lexing, and tables and pictures aren’t modeled. Errors are returned as LexerError or ParserError.

Installation#

Shell
cargo add rtf-parser

Basic usage: extract text from an RTF file#

Rust
use rtf_parser::RtfDocument;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let doc = RtfDocument::from_filepath("letter.rtf")?;
    println!("{}", doc.get_text());
    Ok(())
}

RtfDocument also implements TryFrom<&str>, TryFrom<String> and TryFrom<&mut File>.

How to parse an RTF string step by step#

Rust
use rtf_parser::{Lexer, Parser};

let rtf = r#"{\rtf1\ansi{\fonttbl\f0\fswiss Helvetica;}\f0\pard Some {\b bold} text.\par}"#;
let tokens = Lexer::scan(rtf)?;
let doc = Parser::new(tokens).parse()?;
for block in &doc.body {
    println!("{:?} bold={} {:?}", block.text, block.painter.bold, block.paragraph.alignment);
}

How to read fonts and colors#

Rust
for (num, font) in &doc.header.font_table {
    println!("f{num}: {} ({:?})", font.name, font.font_family);
}
for (num, c) in &doc.header.color_table {
    println!("color {num}: #{:02x}{:02x}{:02x}", c.red, c.green, c.blue);
}

How to convert to simple HTML#

Rust
fn to_html(doc: &rtf_parser::RtfDocument) -> String {
    let mut out = String::from("<p>");
    for block in &doc.body {
        let mut t = block.text.replace('&', "&amp;").replace('<', "&lt;").replace('\n', "</p>\n<p>");
        if block.painter.bold { t = format!("<b>{t}</b>"); }
        if block.painter.italic { t = format!("<i>{t}</i>"); }
        if block.painter.underline { t = format!("<u>{t}</u>"); }
        out.push_str(&t);
    }
    out.push_str("</p>");
    out
}

Tips#