]> git.proxmox.com Git - rustc.git/blob - vendor/pulldown-cmark/README.md
New upstream version 1.38.0+dfsg1
[rustc.git] / vendor / pulldown-cmark / README.md
1 # pulldown-cmark
2
3 [![Build Status](https://dev.azure.com/raphlinus/pulldown-cmark/_apis/build/status/pulldown-cmark-CI?branchName=master)](https://dev.azure.com/raphlinus/pulldown-cmark/_build/latest?definitionId=2&branchName=master)
4 [![Docs](https://docs.rs/pulldown-cmark/badge.svg)](https://docs.rs/pulldown-cmark)
5 [![Crates.io](https://img.shields.io/crates/v/pulldown-cmark.svg?maxAge=2592000)](https://crates.io/crates/pulldown-cmark)
6
7 [Documentation](https://docs.rs/pulldown-cmark/)
8
9 This library is a pull parser for [CommonMark](http://commonmark.org/), written
10 in [Rust](http://www.rust-lang.org/). It comes with a simple command-line tool,
11 useful for rendering to HTML, and is also designed to be easy to use from as
12 a library.
13
14 It is designed to be:
15
16 * Fast; a bare minimum of allocation and copying
17 * Safe; written in pure Rust with no unsafe blocks
18 * Versatile; in particular source-maps are supported
19 * Correct; the goal is 100% compliance with the [CommonMark spec](http://spec.commonmark.org/)
20
21 Further, it optionally supports parsing footnotes,
22 [Github flavored tables](https://github.github.com/gfm/#tables-extension-),
23 [Github flavored task lists](https://github.github.com/gfm/#task-list-items-extension-) and
24 [strikethrough](https://github.github.com/gfm/#strikethrough-extension-).
25
26 ## Why a pull parser?
27
28 There are many parsers for Markdown and its variants, but to my knowledge none
29 use pull parsing. Pull parsing has become popular for XML, especially for
30 memory-conscious applications, because it uses dramatically less memory than
31 constructing a document tree, but is much easier to use than push parsers. Push
32 parsers are notoriously difficult to use, and also often error-prone because of
33 the need for user to delicately juggle state in a series of callbacks.
34
35 In a clean design, the parsing and rendering stages are neatly separated, but
36 this is often sacrificed in the name of performance and expedience. Many Markdown
37 implementations mix parsing and rendering together, and even designs that try
38 to separate them (such as the popular [hoedown](https://github.com/hoedown/hoedown)),
39 make the assumption that the rendering process can be fully represented as a
40 serialized string.
41
42 Pull parsing is in some sense the most versatile architecture. It's possible to
43 drive a push interface, also with minimal memory, and quite straightforward to
44 construct an AST. Another advantage is that source-map information (the mapping
45 between parsed blocks and offsets within the source text) is readily available;
46 you can call `into_offset_iter()` to create an iterator that yields `(Event, Range)`
47 pairs, where the second element is the event's corresponding range in the source
48 document.
49
50 While manipulating ASTs is the most flexible way to transform documents,
51 operating on iterators is surprisingly easy, and quite efficient. Here, for
52 example, is the code to transform soft line breaks into hard breaks:
53
54 ```rust
55 let parser = parser.map(|event| match event {
56 Event::SoftBreak => Event::HardBreak,
57 _ => event
58 });
59 ```
60
61 Or expanding an abbreviation in text:
62
63 ```rust
64 let parser = parser.map(|event| match event {
65 Event::Text(text) => Event::Text(text.replace("abbr", "abbreviation").into()),
66 _ => event
67 });
68 ```
69
70 Another simple example is code to determine the max nesting level:
71
72 ```rust
73 let mut max_nesting = 0;
74 let mut level = 0;
75 for event in parser {
76 match event {
77 Event::Start(_) => {
78 level += 1;
79 max_nesting = std::cmp::max(max_nesting, level);
80 }
81 Event::End(_) => level -= 1,
82 _ => ()
83 }
84 }
85 ```
86
87 There are some basic but fully functional examples of the usage of the crate in the
88 `examples` directory of this repository.
89
90 ## Using Rust idiomatically
91
92 A lot of the internal scanning code is written at a pretty low level (it
93 pretty much scans byte patterns for the bits of syntax), but the external
94 interface is designed to be idiomatic Rust.
95
96 Pull parsers are at heart an iterator of events (start and end tags, text,
97 and other bits and pieces). The parser data structure implements the
98 Rust Iterator trait directly, and Event is an enum. Thus, you can use the
99 full power and expressivity of Rust's iterator infrastructure, including
100 for loops and `map` (as in the examples above), collecting the events into
101 a vector (for recording, playback, and manipulation), and more.
102
103 Further, the `Text` event (representing text) is a small copy-on-write string.
104 The vast majority of text fragments are just
105 slices of the source document. For these, copy-on-write gives a convenient
106 representation that requires no allocation or copying, but allocated
107 strings are available when they're needed. Thus, when rendering text to
108 HTML, most text is copied just once, from the source document to the
109 HTML buffer.
110
111 When using the pulldown-cmark's own HTML renderer, make sure to write to a buffered
112 target like a `Vec<u8>` or `String`. Since it performs many (very) small writes, writing
113 directly to stdout, files, or sockets is detrimental to performance. Such writers can
114 be wrapped in a [`BufWriter`](https://doc.rust-lang.org/std/io/struct.BufWriter.html).
115
116 ## Build options
117
118 By default, the binary is built as well. If you don't want/need it, then build like this:
119
120 ```bash
121 > cargo build --no-default-features
122 ```
123
124 Or put in your `Cargo.toml` file:
125
126 ```toml
127 pulldown-cmark = { version = "0.5", default-features = false }
128 ```
129
130 SIMD accelerated scanners are available for the x64 platform from version 0.5 onwards. To
131 enable them, build with simd feature:
132
133 ```bash
134 > cargo build --release --features simd
135 ```
136
137 Or add the feature to your project's `Cargo.toml`:
138
139 ```toml
140 pulldown-cmark = { version = "0.5", default-features = false, features = ["simd"] }
141 ```
142
143 ## Authors
144
145 The main author is Raph Levien. The implementation of the new design (v0.3+) was completed by Marcus Klaas de Vries.
146
147 ## Contributions
148
149 We gladly accept contributions via GitHub pull requests. Please see
150 [CONTRIBUTING.md](CONTRIBUTING.md) for more details.