textlane_html/models/options.rs
1use std::collections::{BTreeMap, HashMap};
2
3use serde::Deserialize;
4
5/// `html.stringify`: hast into HTML; options named as hast-util-to-html names them.
6#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
7#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
8#[serde(default, rename_all = "camelCase")]
9#[cfg_attr(feature = "schema", schemars(rename = "StringifyOptions"))]
10pub struct Stringify {
11 /// Write raw nodes as they are instead of escaping them.
12 pub allow_dangerous_html: bool,
13 /// Leave characters that are only dangerous in some contexts, such as `` ` ``, as they are.
14 pub allow_dangerous_characters: bool,
15 /// Leave characters as they are where browsers accept them though the spec does not.
16 pub allow_parse_errors: bool,
17 /// Write comments as bogus comments, `<?a>`.
18 pub bogus_comments: bool,
19 /// Close empty foreign elements, `<a />`.
20 pub close_empty_elements: bool,
21 /// Close void elements, `<br />`.
22 pub close_self_closing: bool,
23 /// Write empty attributes as bare names, `a` rather than `a=""`.
24 pub collapse_empty_attributes: bool,
25 /// Leave out tags the HTML spec lets a parser imply.
26 pub omit_optional_tags: bool,
27 /// Leave attribute values unquoted where that is safe.
28 pub prefer_unquoted: bool,
29 /// The quote attribute values are wrapped in: `"` or `'`.
30 pub quote: Option<String>,
31 /// Use the other quote when the value holds more of the preferred one.
32 pub quote_smart: bool,
33 /// The space the tree is in: `html` or `svg`.
34 pub space: Option<String>,
35 /// Leave out the space between quoted attributes.
36 pub tight_attributes: bool,
37 /// Join comma-separated values with `,` rather than `, `.
38 pub tight_comma_separated_lists: bool,
39 /// Write `<!doctypehtml>`.
40 pub tight_doctype: bool,
41 /// Leave out the space before `/>` when the attributes allow.
42 pub tight_self_closing: bool,
43 /// Write `<!DOCTYPE html>`.
44 pub upper_doctype: bool,
45 /// The tag names of void elements, which have no closing tag.
46 pub voids: Option<Vec<String>>,
47}
48
49/// `html.parse`: HTML into hast; options named as rehype-parse names them.
50#[derive(Clone, Debug, Default, Deserialize)]
51#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
52#[serde(default, rename_all = "camelCase")]
53#[cfg_attr(feature = "schema", schemars(rename = "ParseOptions"))]
54pub struct Parse {
55 /// Parse a fragment, as in a `template`, rather than a whole document.
56 pub fragment: bool,
57 /// Report parse errors as messages on the file.
58 pub emit_parse_errors: bool,
59 /// Add the positions of opening and closing tags and attributes to elements.
60 pub verbose: bool,
61}
62
63/// `html.sanitize`: keep only what a schema allows; options: hast-util-sanitize's schema,
64/// where a field left out keeps the default schema's, which is GitHub's.
65#[derive(Clone, Debug, Default, Deserialize)]
66#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
67#[serde(default, rename_all = "camelCase")]
68#[cfg_attr(feature = "schema", schemars(rename = "SanitizeOptions"))]
69pub struct Sanitize {
70 /// Keep comments.
71 pub allow_comments: Option<bool>,
72 /// Keep doctypes.
73 pub allow_doctypes: Option<bool>,
74 /// Elements allowed only inside one of these ancestors, by tag name.
75 pub ancestors: Option<HashMap<String, Vec<String>>>,
76 /// Properties allowed per tag name, `*` for every element; a list names a property and
77 /// the values it may have.
78 pub attributes: Option<HashMap<String, Vec<AttributeDefinition>>>,
79 /// Properties whose values get `clobber_prefix`, so they cannot clobber globals.
80 pub clobber: Option<Vec<String>>,
81 /// The prefix of clobbered values.
82 pub clobber_prefix: Option<String>,
83 /// URL properties and the protocols they may use.
84 pub protocols: Option<HashMap<String, Vec<String>>>,
85 /// Properties set on elements whatever they had, by tag name.
86 pub required: Option<HashMap<String, BTreeMap<String, Primitive>>>,
87 /// Elements dropped with their content rather than unwrapped.
88 pub strip: Option<Vec<String>>,
89 /// The elements kept.
90 pub tag_names: Option<Vec<String>>,
91}
92
93/// A property a sanitize schema allows: by name, or a name and its allowed values.
94#[derive(Clone, Debug, Deserialize)]
95#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
96#[serde(untagged)]
97pub enum AttributeDefinition {
98 Name(String),
99 Values(Vec<Primitive>),
100}
101
102/// A primitive property value.
103#[derive(Clone, Debug, PartialEq, Deserialize)]
104#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
105#[serde(untagged)]
106pub enum Primitive {
107 Boolean(bool),
108 Number(f64),
109 String(String),
110}
111
112/// `html.highlight`: code blocks colored as Shiki colors them, natively by giallo;
113/// options named as @shikijs/rehype names them.
114#[derive(Clone, Debug, Default, Deserialize)]
115#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
116#[serde(default, rename_all = "camelCase")]
117#[cfg_attr(feature = "schema", schemars(rename = "HighlightOptions"))]
118pub struct Highlight {
119 /// The theme of each color mode, `light` first, as `{"light": …, "dark": …}`.
120 pub themes: Option<serde_json::Map<String, serde_json::Value>>,
121 /// The one theme, when `themes` is not given.
122 pub theme: Option<String>,
123 /// The language of a block that names none; such a block is left alone without it.
124 pub default_language: Option<String>,
125 /// The language of a block naming one Shiki does not know; left alone without it.
126 pub fallback_language: Option<String>,
127 /// Colors to replace, by their lowercase spelling: a color for every theme, or a theme's
128 /// name to a map of its own.
129 pub color_replacements: BTreeMap<String, ColorReplacement>,
130 /// Add `language-<name>` to each highlighted `<code>`.
131 pub add_language_class: bool,
132 /// Highlight inline code too, by how it names its language: `tailing-curly-colon`
133 /// reads `` `a(){:js}` ``.
134 pub inline: Option<InlineCode>,
135 /// The `<pre>` property that gets a block's meta, the text after its language; the JSON
136 /// stand-in for `parseMetaString: meta => ({ [name]: meta })`.
137 pub meta_property: Option<String>,
138 /// The transformers of @shikijs/transformers to run, in order, by name or with options.
139 pub transformers: Vec<HighlightTransformer>,
140 /// Lines at least this long, in UTF-16 units, are left one plain token as Shiki's own
141 /// option leaves them; 2,000 when left out, where Shiki has no limit, since a grammar's
142 /// time grows with the square of a line's length. `0` lifts it.
143 pub tokenize_max_line_length: Option<usize>,
144 /// Attributes of a block's `<code>` or `<pre>` listing lines, `2,4-5`, each to the
145 /// classes those lines get, or to `{line, pre}`, the second for the `<pre>`:
146 /// `{"data-focus": {"line": "focused", "pre": "has-focused"}}`.
147 pub line_attributes: BTreeMap<String, LineMark>,
148 /// The attribute of a block's `<code>` or `<pre>` listing words, separated by commas,
149 /// marked at every place as `metaWordHighlight` marks a meta's `/word/`.
150 pub word_attribute: Option<String>,
151 /// The attribute of a block's `<code>` or `<pre>` that numbers its lines as
152 /// `renderLineNumber` does, from its value, or 1 when it is empty.
153 pub line_number_attribute: Option<String>,
154 /// Leave a block alone when its code holds elements, such as `<mark>`, which
155 /// highlighting would flatten into text.
156 pub skip_elements: bool,
157 /// Keep the properties of a block's `<pre>` and `<code>`, such as `data-title`, on the
158 /// ones Shiki makes, merging classes; Shiki's own win where both set one.
159 pub keep_properties: bool,
160}
161
162/// The classes the lines a `lineAttributes` attribute lists get, and maybe its `<pre>`.
163#[derive(Clone, Debug, Deserialize)]
164#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
165#[serde(untagged)]
166pub enum LineMark {
167 /// Classes for each line listed.
168 Line(Classes),
169 /// Classes for each line listed and for the `<pre>` of a block listing any.
170 Both {
171 line: Classes,
172 #[serde(default)]
173 pre: Option<Classes>,
174 },
175}
176
177/// A replacement color, or a theme's own replacements.
178#[derive(Clone, Debug, Deserialize)]
179#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
180#[serde(untagged)]
181pub enum ColorReplacement {
182 Color(String),
183 Theme(BTreeMap<String, String>),
184}
185
186/// How inline code names its language.
187#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
188#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
189pub enum InlineCode {
190 #[serde(rename = "tailing-curly-colon")]
191 TailingCurlyColon,
192 /// Inline `<code>` naming its language by class, `language-js`, as blocks do.
193 #[serde(rename = "class")]
194 Class,
195}
196
197/// A transformer of @shikijs/transformers: its name alone, or its name and options.
198#[derive(Clone, Debug, Deserialize)]
199#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
200#[serde(untagged)]
201pub enum HighlightTransformer {
202 Name(TransformerName),
203 Configured(ConfiguredTransformer),
204}
205
206/// The transformers `html.highlight` runs natively.
207#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
208#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
209#[serde(rename_all = "camelCase")]
210pub enum TransformerName {
211 NotationDiff,
212 NotationFocus,
213 NotationHighlight,
214 NotationErrorLevel,
215 MetaHighlight,
216 MetaWordHighlight,
217 RenderLineNumber,
218}
219
220/// A transformer with its options, as @shikijs/transformers names them.
221#[derive(Clone, Debug, Deserialize)]
222#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
223#[serde(tag = "name", rename_all = "camelCase")]
224pub enum ConfiguredTransformer {
225 /// `[!code ++]` and `[!code --]` mark added and removed lines.
226 #[serde(rename_all = "camelCase")]
227 NotationDiff {
228 class_line_add: Option<Classes>,
229 class_line_remove: Option<Classes>,
230 class_active_pre: Option<Classes>,
231 class_active_code: Option<Classes>,
232 },
233 /// `[!code focus]` marks focused lines.
234 #[serde(rename_all = "camelCase")]
235 NotationFocus {
236 class_active_line: Option<Classes>,
237 class_active_pre: Option<Classes>,
238 class_active_code: Option<Classes>,
239 },
240 /// `[!code highlight]` and `[!code hl]` mark highlighted lines.
241 #[serde(rename_all = "camelCase")]
242 NotationHighlight {
243 class_active_line: Option<Classes>,
244 class_active_pre: Option<Classes>,
245 class_active_code: Option<Classes>,
246 },
247 /// `[!code error]`, `[!code warning]` and `[!code info]` mark lines by level.
248 #[serde(rename_all = "camelCase")]
249 NotationErrorLevel {
250 class_map: Option<BTreeMap<String, Classes>>,
251 class_active_pre: Option<Classes>,
252 class_active_code: Option<Classes>,
253 },
254 /// `{1,3-5}` in the meta marks highlighted lines.
255 #[serde(rename_all = "camelCase")]
256 MetaHighlight {
257 class_name: Option<Classes>,
258 #[serde(default)]
259 zero_indexed: bool,
260 },
261 /// `/word/` in the meta marks every occurrence of the word.
262 #[serde(rename_all = "camelCase")]
263 MetaWordHighlight { class_name: Option<Classes> },
264 /// A number at the start of each line.
265 #[serde(rename_all = "camelCase")]
266 RenderLineNumber {
267 class_line_number: Option<Classes>,
268 start: Option<usize>,
269 },
270}
271
272/// Class names: a list, or one string of them separated by white space.
273#[derive(Clone, Debug, Deserialize)]
274#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
275#[serde(untagged)]
276pub enum Classes {
277 One(String),
278 Many(Vec<String>),
279}
280
281/// `html.externalLinks`: `rel`, `target` and more on links to other sites, as
282/// rehype-external-links adds them; options named as it names them, JSON values only.
283#[derive(Clone, Debug, Default, Deserialize)]
284#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
285#[serde(default, rename_all = "camelCase")]
286#[cfg_attr(feature = "schema", schemars(rename = "ExternalLinksOptions"))]
287pub struct ExternalLinks {
288 /// The `target` of each external link, such as `_blank`.
289 pub target: Option<String>,
290 /// The `rel` of each external link: a list, or tokens separated by white space;
291 /// `nofollow` when left out or empty, none for an empty list.
292 pub rel: Option<Tokens>,
293 /// The protocols of absolute URLs that count as external; `http` and `https` when left
294 /// out. A protocol-relative `//…` URL always counts.
295 pub protocols: Option<Vec<String>>,
296 /// More properties for each external link, as hast names them.
297 pub properties: Option<serde_json::Map<String, serde_json::Value>>,
298 /// hast content appended to each external link in a `<span>`: one node or a list.
299 pub content: Option<serde_json::Value>,
300 /// The properties of that `<span>`.
301 pub content_properties: Option<serde_json::Map<String, serde_json::Value>>,
302}
303
304/// Tokens: a list, or one string of them separated by white space.
305#[derive(Clone, Debug, Deserialize)]
306#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
307#[serde(untagged)]
308pub enum Tokens {
309 One(String),
310 Many(Vec<String>),
311}
312
313/// `html.katex`: math rendered as rehype-katex renders it, natively by katex-rs; options
314/// named as KaTeX names them.
315#[derive(Clone, Debug, Default, Deserialize)]
316#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
317#[serde(default, rename_all = "camelCase")]
318#[cfg_attr(feature = "schema", schemars(rename = "KatexOptions"))]
319pub struct Katex {
320 /// The markup to write, both HTML and MathML by default.
321 pub output: Option<KatexOutput>,
322 /// Put equation numbers on the left.
323 pub leqno: bool,
324 /// Align display math to the left instead of centering it.
325 pub fleqn: bool,
326 /// The color of math that fails to render, `#cc0000` by default.
327 pub error_color: Option<String>,
328 /// Macros by name, each to the TeX it expands to, as `{"\\RR": "\\mathbb{R}"}`.
329 pub macros: BTreeMap<String, String>,
330 /// The thinnest a rule, such as a fraction line, is drawn, in ems.
331 pub min_rule_thickness: Option<f64>,
332 /// Let `\color` color the text after it, as LaTeX does.
333 pub color_is_text_color: bool,
334 /// What to do with input LaTeX would reject: `true` or `"error"` fails it, `"warn"`
335 /// prints a warning, `false` or `"ignore"` (the default) accepts it.
336 pub strict: Option<KatexStrict>,
337 /// Allow commands that can run untrusted input, such as `\href` and `\includegraphics`.
338 pub trust: bool,
339 /// The largest a user-given size may be, in ems.
340 pub max_size: Option<f64>,
341 /// How many macro expansions one formula may take, 1000 by default.
342 pub max_expand: Option<usize>,
343 /// Let definitions such as `\def` last past the formula they are in.
344 pub global_group: bool,
345 /// Elements, by tag name, that hold math besides the classed ones, such as
346 /// `my-math`; one is display math when it has a `display` attribute other than
347 /// `inline`.
348 pub tag_names: Vec<String>,
349}
350
351/// The markup KaTeX writes.
352#[derive(Clone, Copy, Debug, PartialEq, Deserialize)]
353#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
354#[serde(rename_all = "camelCase")]
355pub enum KatexOutput {
356 Html,
357 Mathml,
358 HtmlAndMathml,
359}
360
361/// How strictly KaTeX holds input to LaTeX.
362#[derive(Clone, Debug, PartialEq, Deserialize)]
363#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
364#[serde(untagged)]
365pub enum KatexStrict {
366 Boolean(bool),
367 Mode(KatexStrictMode),
368}
369
370/// One level of KaTeX's strictness.
371#[derive(Clone, Copy, Debug, PartialEq, Deserialize)]
372#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
373#[serde(rename_all = "camelCase")]
374pub enum KatexStrictMode {
375 Ignore,
376 Warn,
377 Error,
378}
379
380/// `html.extractToc`: the headings, nested by rank, as the file's `data.toc`, as
381/// @stefanprobst/rehype-extract-toc stores them.
382#[derive(Clone, Debug, Default, Deserialize)]
383#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
384#[serde(default, rename_all = "camelCase")]
385#[cfg_attr(feature = "schema", schemars(rename = "ExtractTocOptions"))]
386pub struct ExtractToc {
387 /// Attributes, such as `data-toc-hidden`, that keep a heading out of the table of
388 /// contents, or `name=value`, such as `data-toc=false`, for one value of it; what would
389 /// nest under it nests under the heading before.
390 pub skip: Vec<String>,
391 /// Elements, by tag name, whose headings stay out, such as a card's title.
392 pub skip_inside: Vec<String>,
393 /// The shallowest heading rank listed, 1 to 6.
394 pub min_depth: Option<u8>,
395 /// The deepest heading rank listed, 1 to 6.
396 pub max_depth: Option<u8>,
397}
398
399/// `html.slug`: ids on headings, from their text; options named as rehype-slug names
400/// them.
401#[derive(Clone, Debug, Default, Deserialize)]
402#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
403#[serde(default, rename_all = "camelCase")]
404#[cfg_attr(feature = "schema", schemars(rename = "SlugOptions"))]
405pub struct Slug {
406 /// Put before each id.
407 pub prefix: String,
408 /// Count the ids already in the document as taken, so a generated id never repeats one
409 /// a link may point at.
410 pub reserve_existing: bool,
411 /// The heading ranks, 1 to 6, that get ids; every heading when left out.
412 pub ranks: Option<Vec<u8>>,
413 /// Link each heading with an `id` to itself, as rehype-autolink-headings does: `true`, or
414 /// its options.
415 pub autolink: Option<Autolink>,
416}
417
418/// `html.slug`'s `autolink`: on, or on with rehype-autolink-headings' options.
419#[derive(Clone, Debug, Deserialize)]
420#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
421#[serde(untagged)]
422pub enum Autolink {
423 Enabled(bool),
424 Options(Box<AutolinkOptions>),
425}
426
427/// rehype-autolink-headings' options, JSON values only.
428#[derive(Clone, Debug, Default, Deserialize)]
429#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
430#[serde(default, rename_all = "camelCase")]
431pub struct AutolinkOptions {
432 /// Where the link goes: in the heading first or last, around its content, or before or
433 /// after it.
434 pub behavior: AutolinkBehavior,
435 /// The link's properties, as hast names them; `ariaHidden` and `tabIndex: -1` for
436 /// `prepend` and `append` when left out.
437 pub properties: Option<serde_json::Map<String, serde_json::Value>>,
438 /// hast content of the link, one node or a list; `<span class="icon icon-link">` when
439 /// left out, except for `wrap`, which appends it to the heading's content.
440 pub content: Option<serde_json::Value>,
441 /// A hast element wrapping the heading and its link, for `before` and `after`.
442 pub group: Option<serde_json::Value>,
443 /// Properties set on each linked heading.
444 pub heading_properties: Option<serde_json::Map<String, serde_json::Value>>,
445 /// The tag names of the headings to link; every heading when left out.
446 pub test: Option<TagNames>,
447}
448
449/// Where `autolink` puts each heading's link.
450#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Deserialize)]
451#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
452#[serde(rename_all = "lowercase")]
453pub enum AutolinkBehavior {
454 #[default]
455 Prepend,
456 Append,
457 Wrap,
458 Before,
459 After,
460}
461
462/// One tag name or several.
463#[derive(Clone, Debug, Deserialize)]
464#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
465#[serde(untagged)]
466pub enum TagNames {
467 One(String),
468 Many(Vec<String>),
469}
470
471/// `html.toMarkdown`: hast into mdast; options named as hast-util-to-mdast names them.
472#[derive(Clone, Debug, Default, Deserialize)]
473#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
474#[serde(default, rename_all = "camelCase")]
475#[cfg_attr(feature = "schema", schemars(rename = "ToMarkdownOptions"))]
476pub struct ToMarkdown {
477 /// Wrap all phrasing content of the root in paragraphs, as for a whole document.
478 pub document: bool,
479 /// Collapse whitespace holding a line ending to that line ending instead of a space.
480 pub newlines: bool,
481 /// The text of a checked checkbox or radio, `[x]` by default.
482 pub checked: Option<String>,
483 /// The text of an unchecked checkbox or radio, `[ ]` by default.
484 pub unchecked: Option<String>,
485 /// The quotes `<q>` uses, an opening and closing character each, alternating by how
486 /// deep it nests; `"` by default.
487 pub quotes: Option<Vec<String>>,
488 /// Turn MathML `<math>` holding a TeX annotation, as `html.katex` writes it, into math
489 /// nodes, `$…$` once `md.math` writes them, display math for `display="block"`, and
490 /// drop KaTeX's visual `katex-html` copy.
491 pub math: bool,
492 /// Attributes of a code block's `<pre>` or `<code>` written into its meta, each to the
493 /// key it takes there: `{"data-title": "title"}` makes `title="a.js"`.
494 pub code_meta: BTreeMap<String, String>,
495}
496
497/// `html.raw`: reparse raw HTML and fix nesting through the HTML parser; options named as
498/// hast-util-raw names them.
499#[derive(Clone, Debug, Default, Deserialize)]
500#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
501#[serde(default, rename_all = "camelCase")]
502#[cfg_attr(feature = "schema", schemars(rename = "RawOptions"))]
503pub struct Raw {
504 /// Node types, unknown to hast, to copy through as they are; their children are
505 /// reparsed on their own.
506 pub pass_through: Vec<String>,
507 /// Escape the opening `<` of the tags GFM's tagfilter disallows in raw nodes.
508 pub tagfilter: bool,
509}
510
511/// `html.format`: indent and collapse whitespace for readable HTML; options named as
512/// hast-util-format names them.
513#[derive(Clone, Debug, Default, Deserialize)]
514#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
515#[serde(default, rename_all = "camelCase")]
516#[cfg_attr(feature = "schema", schemars(rename = "FormatOptions"))]
517pub struct Format {
518 /// Tag names of elements to put a blank line between, when both are one.
519 pub blanks: Vec<String>,
520 /// One level of indentation: a number of spaces or the text itself; two spaces when
521 /// left out.
522 pub indent: Option<Indent>,
523 /// Indent the first level, usually `<html>`'s `head` and `body`; `true` when left out.
524 pub indent_initial: Option<bool>,
525 /// Only collapse whitespace, as rehype-minify-whitespace does, adding no line endings or
526 /// indentation; `{ newlines: true }` collapses a run holding a line ending to it.
527 pub minify: Option<Minify>,
528}
529
530/// `html.format`'s `minify`: on, or on with rehype-minify-whitespace's options.
531#[derive(Clone, Debug, Deserialize)]
532#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
533#[serde(untagged)]
534pub enum Minify {
535 Enabled(bool),
536 Options(MinifyOptions),
537}
538
539/// rehype-minify-whitespace's options.
540#[derive(Clone, Debug, Default, Deserialize)]
541#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
542#[serde(default, rename_all = "camelCase")]
543pub struct MinifyOptions {
544 /// Collapse a run of whitespace holding a line ending to a line ending, not a space.
545 pub newlines: bool,
546}
547
548impl Format {
549 /// Whether to only minify, and with `newlines`.
550 pub(crate) fn minify_newlines(&self) -> Option<bool> {
551 match &self.minify {
552 Some(Minify::Enabled(true)) => Some(false),
553 Some(Minify::Options(options)) => Some(options.newlines),
554 Some(Minify::Enabled(false)) | None => None,
555 }
556 }
557}
558
559/// One level of indentation.
560#[derive(Clone, Debug, Deserialize)]
561#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
562#[serde(untagged)]
563pub enum Indent {
564 Spaces(usize),
565 Text(String),
566}
567
568/// The elements prose plugins leave alone when `ignore` is left out: links, code, scripts,
569/// form text and foreign content.
570pub const PROSE_IGNORE: &[&str] = &[
571 "a", "code", "pre", "kbd", "samp", "script", "style", "textarea", "title", "math",
572 "svg",
573];
574
575/// `html.math`: `$…$` and `$$…$$` in text into the elements `html.katex` renders, read by
576/// pandoc's rule so prices stay text: an opening `$` is followed by a non-space, a closing
577/// one follows a non-space and is not followed by a digit; `\$` is a dollar sign.
578#[derive(Clone, Debug, Deserialize)]
579#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
580#[serde(default, rename_all = "camelCase")]
581#[cfg_attr(feature = "schema", schemars(rename = "MathOptions"))]
582pub struct Math {
583 /// Let one dollar, `$a$`, form math, as well as two.
584 pub single_dollar_text_math: bool,
585 /// Elements, by tag name, whose text is left alone; links, code, scripts, form text,
586 /// `math` and `svg` when left out.
587 pub ignore: Option<Vec<String>>,
588 /// Attributes, such as `data-literal`, whose elements' text is left alone.
589 pub ignore_attributes: Vec<String>,
590}
591
592impl Default for Math {
593 fn default() -> Self {
594 Math {
595 single_dollar_text_math: true,
596 ignore: None,
597 ignore_attributes: Vec::new(),
598 }
599 }
600}
601
602/// `html.linkify`: bare URLs and email addresses in text into links, as GitHub's literal
603/// autolinks do: an `http`, `https` or `ftp` URL as it is, a `www.` one under `https://`,
604/// an email under `mailto:`; any other scheme stays text.
605#[derive(Clone, Debug, Default, Deserialize)]
606#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
607#[serde(default, rename_all = "camelCase")]
608#[cfg_attr(feature = "schema", schemars(rename = "LinkifyOptions"))]
609pub struct Linkify {
610 /// Elements, by tag name, whose text is left alone; links, code, scripts, form text,
611 /// `math` and `svg` when left out.
612 pub ignore: Option<Vec<String>>,
613 /// Attributes, such as `data-literal`, whose elements' text is left alone.
614 pub ignore_attributes: Vec<String>,
615}
616
617/// `html.gemoji`: gemoji shortcodes in text, `:smile:`, into emoji, as `md.gemoji` does in
618/// Markdown.
619#[derive(Clone, Debug, Default, Deserialize)]
620#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
621#[serde(default, rename_all = "camelCase")]
622#[cfg_attr(feature = "schema", schemars(rename = "GemojiOptions"))]
623pub struct Gemoji {
624 /// Wrap each emoji in `<span role="img" aria-label="…">`, labelled with its name.
625 pub accessible: bool,
626 /// Elements, by tag name, whose text is left alone; links, code, scripts, form text,
627 /// `math` and `svg` when left out.
628 pub ignore: Option<Vec<String>>,
629 /// Attributes, such as `data-literal`, whose elements' text is left alone.
630 pub ignore_attributes: Vec<String>,
631}
632
633/// `html.pathRewrite`: the URLs of a document's attributes as a site serves them, as
634/// `md.pathRewrite` does for Markdown: relative ones resolved against the file's path and
635/// made root-relative, every root-relative one under `base`, and links to a page's file
636/// turned into its URL.
637#[derive(Clone, Debug, Default, Deserialize)]
638#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
639#[serde(default, rename_all = "camelCase")]
640#[cfg_attr(feature = "schema", schemars(rename = "PathRewriteOptions"))]
641pub struct PathRewrite {
642 /// The directory URLs count from, as the file's path spells it; the path's own
643 /// starting point when left out.
644 pub root: Option<String>,
645 /// The URL the site is served at, such as `/docs`, put before every root-relative URL
646 /// once.
647 pub base: Option<String>,
648 /// Files, relative to `root`, to the URL of their page, such as
649 /// `{"guide.html": "/guide/"}`; an `href` naming one takes it.
650 pub pages: BTreeMap<String, String>,
651 /// The attributes whose URLs are rewritten; `href`, `src`, `srcset` and `poster` when
652 /// left out.
653 pub attributes: Option<Vec<String>>,
654}