html_escape/lib.rs
1/*!
2# HTML Escape
3
4This library is for encoding/escaping special characters in HTML and decoding/unescaping HTML entities as well.
5
6## Usage
7
8### Encoding
9
10This crate provides some `encode_*` functions to encode HTML text in different situations.
11
12Escaping is context-sensitive.
13Use `encode_text` for text, quoted attribute encoders for quoted attributes, `encode_unquoted_attribute` for unquoted attributes, and script or style encoders for raw-text elements.
14`encode_safe` is not a context-independent sanitizer.
15
16For example, to put a text between a start tag `<foo>` and an end tag `</foo>`, use the `encode_text` function to escape every `&`, `<`, and `>` in the text.
17
18```rust
19assert_eq!("a > b && a < c", html_escape::encode_text("a > b && a < c"));
20```
21
22The script and style `*_quoted_text` functions take raw string content and do not add outer quotes.
23They escape every backslash, including those in existing escape sequences, and also C0 control characters and every `<`.
24Script variants also escape U+2028 and U+2029.
25Style variants replace NUL with U+FFFD, so an input containing NUL cannot round-trip without a change.
26Use these functions for single-quoted or double-quoted string content inside `<script>` or `<style>`.
27
28Since 0.3.0, the `*_quoted_text` encoders escape every input backslash.
29Pass the original text and remove manual string escaping at the call site; for example, pass `C:\temp\file` instead of `C:\\temp\\file`.
30Their decoders also decode escaped backslashes and hex escapes.
31They still recognize legacy tag and comment escapes, but some decoding results differ from 0.2.
32
33```rust
34let text = r"C:\temp\file";
35assert_eq!(r"C:\\temp\\file", html_escape::encode_script_single_quoted_text(text));
36assert_eq!(text, html_escape::decode_script_single_quoted_text(r"C:\\temp\\file"));
37assert_eq!("\n", html_escape::decode_script_single_quoted_text(r"\x0A"));
38assert_eq!(r"\x0A", html_escape::decode_script_single_quoted_text(r"\\x0A"));
39```
40
41`encode_script` and `encode_style` scan the whole element text without parsing JavaScript or CSS.
42They insert backslashes before tag and comment sequences, so check that the result is valid in the target language.
43They keep existing escapes, so encoding and decoding may not return the original text.
44For example, `<\/script>` stays the same during script encoding, but script decoding changes it to `</script>`.
45`encode_script` is not a JSON encoder; its `\!` escape for `<!--` is not valid JSON.
46To put JSON inside `<script type="application/json">`, serialize the data as JSON first, then replace each literal `<` with `\u003C` in the JSON text.
47
48```rust
49let json = r#"{"text":"<!--</script>"}"#;
50let escaped_json = json.replace('<', r"\u003C");
51let html = format!(r#"<script type="application/json">{}</script>"#, escaped_json);
52assert_eq!(r#"<script type="application/json">{"text":"\u003C!--\u003C/script>"}</script>"#, html);
53```
54
55The functions suffixed with `_to_writer`, `_to_vec` or `_to_string` are useful to generate HTML.
56The `_to_string` and `_to_vec` functions append to the output and return only the slice written by the current call.
57The `_to_writer` functions accept writers including `&mut dyn std::io::Write`.
58Pass the whole element source in one call to `encode_script` or `encode_style`, including their output variants; separate calls do not share tag-matching state.
59Quoted string encoders can be appended in chunks because they escape every `<`.
60For an empty attribute value, use a quoted attribute; the unquoted attribute encoder does not add quotes.
61
62```rust
63let mut html = String::from("<input value=");
64assert_eq!("Hello world!", html_escape::encode_unquoted_attribute_to_string("Hello world!", &mut html));
65html.push_str(" placeholder=\"");
66assert_eq!("The default value is "Hello world!".", html_escape::encode_double_quoted_attribute_to_string("The default value is \"Hello world!\".", &mut html));
67html.push_str("\"/><script>alert('");
68assert_eq!(r"\x3Cscript>\'s end tag is \x3C/script>", html_escape::encode_script_single_quoted_text_to_string("<script>'s end tag is </script>", &mut html));
69html.push_str("');</script>");
70
71assert_eq!(r#"<input value=Hello world! placeholder="The default value is "Hello world!"."/><script>alert('\x3Cscript>\'s end tag is \x3C/script>');</script>"#, html);
72```
73
74### Decoding
75
76Decoding accepts exact named and numeric character references ending with `;`.
77It does not apply legacy semicolonless references or C1 control replacements used by browser tokenizers.
78
79```rust
80assert_eq!("Hello world!", html_escape::decode_html_entities("Hello world!"));
81```
82
83```rust
84assert_eq!("alert('<script></script>');", html_escape::decode_script(r"alert('<script><\/script>');"));
85```
86
87## No Std
88
89Disable the default features to compile this crate without std.
90
91```toml
92[dependencies.html-escape]
93version = "*"
94default-features = false
95```
96
97## Benchmark
98
99```bash
100cargo bench
101```
102*/
103
104#![cfg_attr(not(feature = "std"), no_std)]
105#![cfg_attr(docsrs, feature(doc_cfg))]
106
107extern crate alloc;
108
109mod decode;
110mod encode;
111mod functions;
112
113pub use decode::*;
114pub use encode::*;