max / docengine
6 files changed,
+40 insertions,
-0 deletions
| @@ -63,26 +63,37 @@ | |||
| 63 | 63 | /// A rendered documentation page. | |
| 64 | 64 | #[derive(Clone, Debug)] | |
| 65 | 65 | pub struct DocPage { | |
| 66 | + | /// Page title, from frontmatter or the first heading. | |
| 66 | 67 | pub title: String, | |
| 68 | + | /// URL slug, the file stem. | |
| 67 | 69 | pub slug: String, | |
| 70 | + | /// Section the page belongs to, from its directory. | |
| 68 | 71 | pub section: String, | |
| 72 | + | /// The rendered HTML body. | |
| 69 | 73 | pub html_content: String, | |
| 70 | 74 | } | |
| 71 | 75 | ||
| 72 | 76 | /// Ordered entry for the docs index page. | |
| 73 | 77 | #[derive(Clone, Debug)] | |
| 74 | 78 | pub struct DocIndexEntry { | |
| 79 | + | /// Page title as it should read in the index. | |
| 75 | 80 | pub title: String, | |
| 81 | + | /// URL slug the entry points at. | |
| 76 | 82 | pub slug: String, | |
| 83 | + | /// Section the entry is grouped under. | |
| 77 | 84 | pub section: String, | |
| 78 | 85 | } | |
| 79 | 86 | ||
| 80 | 87 | /// Entry in the full-text search index, serialised to JSON for client-side search. | |
| 81 | 88 | #[derive(Clone, Debug, serde::Serialize)] | |
| 82 | 89 | pub struct DocSearchEntry { | |
| 90 | + | /// URL slug a hit navigates to. | |
| 83 | 91 | pub slug: String, | |
| 92 | + | /// Page title, shown as the hit's label. | |
| 84 | 93 | pub title: String, | |
| 94 | + | /// Section the page belongs to. | |
| 85 | 95 | pub section: String, | |
| 96 | + | /// Page body as plain text, which is what the client-side search matches. | |
| 86 | 97 | pub body_text: String, | |
| 87 | 98 | } | |
| 88 | 99 |
| @@ -5,11 +5,17 @@ | |||
| 5 | 5 | /// Parsed TOML frontmatter from a markdown document. | |
| 6 | 6 | #[derive(Debug, Clone, Default, Deserialize)] | |
| 7 | 7 | pub struct Frontmatter { | |
| 8 | + | /// Document title, overriding whatever the first heading says. | |
| 8 | 9 | pub title: Option<String>, | |
| 10 | + | /// Publication date, kept as written rather than parsed. | |
| 9 | 11 | pub date: Option<String>, | |
| 12 | + | /// Free-form tags. | |
| 10 | 13 | pub tags: Option<Vec<String>>, | |
| 14 | + | /// Section the document belongs to, used for grouping in an index. | |
| 11 | 15 | pub section: Option<String>, | |
| 16 | + | /// Whether the document is a draft and should be withheld. | |
| 12 | 17 | pub draft: Option<bool>, | |
| 18 | + | /// Every other key in the frontmatter, left for the consumer to interpret. | |
| 13 | 19 | #[serde(flatten)] | |
| 14 | 20 | pub extra: HashMap<String, toml::Value>, | |
| 15 | 21 | } |
| @@ -20,6 +20,8 @@ | |||
| 20 | 20 | //! Optional features add document loading, TOML frontmatter, @mention resolution, | |
| 21 | 21 | //! and quote attribution post-processing. | |
| 22 | 22 | ||
| 23 | + | #![warn(missing_docs)] | |
| 24 | + | ||
| 23 | 25 | #[cfg(any(feature = "mentions", test))] | |
| 24 | 26 | mod code_spans; | |
| 25 | 27 | mod escape; |
| @@ -4,8 +4,12 @@ | |||
| 4 | 4 | ||
| 5 | 5 | /// Quote author info for attribution rendering. | |
| 6 | 6 | pub struct QuoteAuthor { | |
| 7 | + | /// Handle the attribution links to. | |
| 7 | 8 | pub username: String, | |
| 9 | + | /// Name shown in the attribution line. | |
| 8 | 10 | pub display_name: String, | |
| 11 | + | /// Whether the account is gone, in which case the attribution renders | |
| 12 | + | /// without a link. | |
| 9 | 13 | pub is_removed: bool, | |
| 10 | 14 | } | |
| 11 | 15 |
| @@ -23,8 +23,11 @@ | |||
| 23 | 23 | /// Result of rendering markdown with metadata. | |
| 24 | 24 | #[derive(Debug, Clone)] | |
| 25 | 25 | pub struct RenderResult { | |
| 26 | + | /// The rendered HTML, already sanitized under the chosen preset. | |
| 26 | 27 | pub html: String, | |
| 28 | + | /// Words in the source markdown, counted before rendering. | |
| 27 | 29 | pub word_count: u32, | |
| 30 | + | /// Reading time for `word_count`, rounded up to whole minutes. | |
| 28 | 31 | pub reading_time_minutes: u32, | |
| 29 | 32 | } | |
| 30 | 33 | ||
| @@ -220,36 +223,42 @@ | |||
| 220 | 223 | } | |
| 221 | 224 | } | |
| 222 | 225 | ||
| 226 | + | /// Enable GFM tables. | |
| 223 | 227 | #[must_use] | |
| 224 | 228 | pub fn with_tables(mut self, enabled: bool) -> Self { | |
| 225 | 229 | self.tables = enabled; | |
| 226 | 230 | self | |
| 227 | 231 | } | |
| 228 | 232 | ||
| 233 | + | /// Enable GFM strikethrough (`~~text~~`). | |
| 229 | 234 | #[must_use] | |
| 230 | 235 | pub fn with_strikethrough(mut self, enabled: bool) -> Self { | |
| 231 | 236 | self.strikethrough = enabled; | |
| 232 | 237 | self | |
| 233 | 238 | } | |
| 234 | 239 | ||
| 240 | + | /// Enable GFM footnotes. | |
| 235 | 241 | #[must_use] | |
| 236 | 242 | pub fn with_footnotes(mut self, enabled: bool) -> Self { | |
| 237 | 243 | self.footnotes = enabled; | |
| 238 | 244 | self | |
| 239 | 245 | } | |
| 240 | 246 | ||
| 247 | + | /// Turn straight quotes and dashes into their typographic forms. | |
| 241 | 248 | #[must_use] | |
| 242 | 249 | pub fn with_smart_punctuation(mut self, enabled: bool) -> Self { | |
| 243 | 250 | self.smart_punctuation = enabled; | |
| 244 | 251 | self | |
| 245 | 252 | } | |
| 246 | 253 | ||
| 254 | + | /// Enable GFM task list items (`- [ ]`). | |
| 247 | 255 | #[must_use] | |
| 248 | 256 | pub fn with_tasklists(mut self, enabled: bool) -> Self { | |
| 249 | 257 | self.tasklists = enabled; | |
| 250 | 258 | self | |
| 251 | 259 | } | |
| 252 | 260 | ||
| 261 | + | /// Drop images, keeping their alt text. | |
| 253 | 262 | #[must_use] | |
| 254 | 263 | pub fn with_strip_images(mut self, enabled: bool) -> Self { | |
| 255 | 264 | self.strip_images = enabled; | |
| @@ -273,18 +282,21 @@ | |||
| 273 | 282 | self | |
| 274 | 283 | } | |
| 275 | 284 | ||
| 285 | + | /// Drop raw HTML in the source rather than passing it to the sanitizer. | |
| 276 | 286 | #[must_use] | |
| 277 | 287 | pub fn with_strip_raw_html(mut self, enabled: bool) -> Self { | |
| 278 | 288 | self.strip_raw_html = enabled; | |
| 279 | 289 | self | |
| 280 | 290 | } | |
| 281 | 291 | ||
| 292 | + | /// Drop link and image URLs whose scheme is not http, https, mailto or ftp. | |
| 282 | 293 | #[must_use] | |
| 283 | 294 | pub fn with_dangerous_scheme_filter(mut self, enabled: bool) -> Self { | |
| 284 | 295 | self.dangerous_scheme_filter = enabled; | |
| 285 | 296 | self | |
| 286 | 297 | } | |
| 287 | 298 | ||
| 299 | + | /// Choose the sanitization preset applied to the rendered HTML. | |
| 288 | 300 | #[must_use] | |
| 289 | 301 | pub fn with_sanitize(mut self, preset: SanitizePreset) -> Self { | |
| 290 | 302 | self.sanitize = preset; |
| @@ -38,8 +38,13 @@ | |||
| 38 | 38 | /// A single entry in a table of contents. | |
| 39 | 39 | #[derive(Debug, Clone, PartialEq, Eq)] | |
| 40 | 40 | pub struct TocEntry { | |
| 41 | + | /// Heading level, 1 for `#` through 6 for `######`. | |
| 41 | 42 | pub level: u8, | |
| 43 | + | /// The heading's text, with inline markup flattened away. | |
| 42 | 44 | pub text: String, | |
| 45 | + | /// Slugified anchor, matching the `id` [`Renderer::with_heading_ids`] emits. | |
| 46 | + | /// | |
| 47 | + | /// [`Renderer::with_heading_ids`]: crate::Renderer::with_heading_ids | |
| 43 | 48 | pub anchor: String, | |
| 44 | 49 | } | |
| 45 | 50 |