Skip to main content

CompileOptions

Struct CompileOptions 

Source
pub struct CompileOptions {
    pub allow_any_img_src: bool,
    pub allow_dangerous_html: bool,
    pub allow_dangerous_protocol: bool,
    pub default_line_ending: LineEnding,
    pub gfm_footnote_back_label: Option<String>,
    pub gfm_footnote_clobber_prefix: Option<String>,
    pub gfm_footnote_label_attributes: Option<String>,
    pub gfm_footnote_label_tag_name: Option<String>,
    pub gfm_footnote_label: Option<String>,
    pub gfm_task_list_item_checkable: bool,
    pub gfm_tagfilter: bool,
    pub heading_ids: bool,
}
Expand description

Configuration that describes how to compile to HTML.

You likely either want to turn on the dangerous options (allow_dangerous_html, allow_dangerous_protocol) when dealing with input you trust, or want to customize how GFM footnotes are compiled (typically because the input markdown is not in English).

§Examples

use socketry_markdown::CompileOptions;

// Use the default trait to get safe defaults:
let safe = CompileOptions::default();

// Live dangerously / trust the author:
let danger = CompileOptions {
  allow_dangerous_html: true,
  allow_dangerous_protocol: true,
  ..CompileOptions::default()
};

// In French:
let enFrançais = CompileOptions {
  gfm_footnote_back_label: Some("Arrière".into()),
  gfm_footnote_label: Some("Notes de bas de page".into()),
  ..CompileOptions::default()
};

Fields§

§allow_any_img_src: bool

Whether to allow all values in images.

The default is false, which lets allow_dangerous_protocol control protocol safety for both links and images.

Pass true to allow all values as src on images, regardless of allow_dangerous_protocol. This is safe because the HTML specification does not allow executable code in images.

§Examples

use socketry_markdown::{to_html_with_options, CompileOptions, Options};

// By default, some protocols in image sources are dropped:
assert_eq!(
    to_html_with_options(
        "![](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)",
        &Options::default()
    )?,
    "<p><img src=\"\" alt=\"\" /></p>"
);

// Turn `allow_any_img_src` on to allow all values as `src` on images.
// This is safe because browsers do not execute code in images.
assert_eq!(
    to_html_with_options(
        "![](javascript:alert(1))",
        &Options {
            compile: CompileOptions {
              allow_any_img_src: true,
              ..CompileOptions::default()
            },
            ..Options::default()
        }
    )?,
    "<p><img src=\"javascript:alert(1)\" alt=\"\" /></p>"
);
§allow_dangerous_html: bool

Whether to allow (dangerous) HTML.

The default is false, which still parses the HTML according to CommonMark but shows the HTML as text instead of as elements.

Pass true for trusted content to get actual HTML elements.

When using GFM, make sure to also turn off gfm_tagfilter. Otherwise, some dangerous HTML is still ignored.

§Examples

use socketry_markdown::{to_html, to_html_with_options, CompileOptions, Options};

// `markdown-rs` is safe by default:
assert_eq!(
    to_html("Hi, <i>venus</i>!"),
    "<p>Hi, &lt;i&gt;venus&lt;/i&gt;!</p>"
);

// Turn `allow_dangerous_html` on to allow potentially dangerous HTML:
assert_eq!(
    to_html_with_options(
        "Hi, <i>venus</i>!",
        &Options {
            compile: CompileOptions {
              allow_dangerous_html: true,
              ..CompileOptions::default()
            },
            ..Options::default()
        }
    )?,
    "<p>Hi, <i>venus</i>!</p>"
);
§allow_dangerous_protocol: bool

Whether to allow dangerous protocols in links and images.

The default is false, which drops URLs in links and images that use dangerous protocols.

Pass true for trusted content to support all protocols.

URLs that have no protocol (which means it’s relative to the current page, such as ./some/page.html) and URLs that have a safe protocol (for images: http, https; for links: http, https, irc, ircs, mailto, xmpp), are safe. All other URLs are dangerous and dropped.

When the option allow_all_protocols_in_img is enabled, allow_dangerous_protocol only applies to links.

This is safe because the HTML specification does not allow executable code in images. All modern browsers respect this.

§Examples

use socketry_markdown::{to_html, to_html_with_options, CompileOptions, Options};

// `markdown-rs` is safe by default:
assert_eq!(
    to_html("<javascript:alert(1)>"),
    "<p><a href=\"\">javascript:alert(1)</a></p>"
);

// Turn `allow_dangerous_protocol` on to allow potentially dangerous protocols:
assert_eq!(
    to_html_with_options(
        "<javascript:alert(1)>",
        &Options {
            compile: CompileOptions {
              allow_dangerous_protocol: true,
              ..CompileOptions::default()
            },
            ..Options::default()
        }
    )?,
    "<p><a href=\"javascript:alert(1)\">javascript:alert(1)</a></p>"
);
§default_line_ending: LineEnding

Default line ending to use when compiling to HTML, for line endings not in value.

Generally, markdown-rs copies line endings (\r, \n, \r\n) in the markdown document over to the compiled HTML. In some cases, such as > a, CommonMark requires that extra line endings are added: <blockquote>\n<p>a</p>\n</blockquote>.

To create that line ending, the document is checked for the first line ending that is used. If there is no line ending, default_line_ending is used. If that isn’t configured, \n is used.

§Examples

use socketry_markdown::{to_html, to_html_with_options, CompileOptions, LineEnding, Options};

// `markdown-rs` uses `\n` by default:
assert_eq!(
    to_html("> a"),
    "<blockquote>\n<p>a</p>\n</blockquote>"
);

// Define `default_line_ending` to configure the default:
assert_eq!(
    to_html_with_options(
        "> a",
        &Options {
            compile: CompileOptions {
              default_line_ending: LineEnding::CarriageReturnLineFeed,
              ..CompileOptions::default()
            },
            ..Options::default()
        }
    )?,
    "<blockquote>\r\n<p>a</p>\r\n</blockquote>"
);
§gfm_footnote_back_label: Option<String>

Textual label to describe the backreference back to footnote calls.

The default value is "Back to content". Change it when the markdown is not in English.

This label is used in the aria-label attribute on each backreference (the ↩ links). It affects users of assistive technology.

§Examples

use socketry_markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};

// `"Back to content"` is used by default:
assert_eq!(
    to_html_with_options(
        "[^a]\n\n[^a]: b",
        &Options::gfm()
    )?,
    "<p><sup><a href=\"#user-content-fn-a\" id=\"user-content-fnref-a\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\">1</a></sup></p>\n<section data-footnotes=\"\" class=\"footnotes\"><h2 id=\"footnote-label\" class=\"sr-only\">Footnotes</h2>\n<ol>\n<li id=\"user-content-fn-a\">\n<p>b <a href=\"#user-content-fnref-a\" data-footnote-backref=\"\" aria-label=\"Back to content\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>\n"
);

// Pass `gfm_footnote_back_label` to use something else:
assert_eq!(
    to_html_with_options(
        "[^a]\n\n[^a]: b",
        &Options {
            parse: ParseOptions::gfm(),
            compile: CompileOptions {
              gfm_footnote_back_label: Some("Arrière".into()),
              ..CompileOptions::gfm()
            }
        }
    )?,
    "<p><sup><a href=\"#user-content-fn-a\" id=\"user-content-fnref-a\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\">1</a></sup></p>\n<section data-footnotes=\"\" class=\"footnotes\"><h2 id=\"footnote-label\" class=\"sr-only\">Footnotes</h2>\n<ol>\n<li id=\"user-content-fn-a\">\n<p>b <a href=\"#user-content-fnref-a\" data-footnote-backref=\"\" aria-label=\"Arrière\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>\n"
);
§gfm_footnote_clobber_prefix: Option<String>

Prefix to use before the id attribute on footnotes to prevent them from clobbering.

The default is "user-content-". Pass Some("".into()) for trusted markdown and when you are careful with polyfilling. You could pass a different prefix.

DOM clobbering is this:

<p id="x"></p>
<script>alert(x) // `x` now refers to the `p#x` DOM element</script>

The above example shows that elements are made available by browsers, by their ID, on the window object. This is a security risk because you might be expecting some other variable at that place. It can also break polyfills. Using a prefix solves these problems.

§Examples

use socketry_markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};

// `"user-content-"` is used by default:
assert_eq!(
    to_html_with_options(
        "[^a]\n\n[^a]: b",
        &Options::gfm()
    )?,
    "<p><sup><a href=\"#user-content-fn-a\" id=\"user-content-fnref-a\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\">1</a></sup></p>\n<section data-footnotes=\"\" class=\"footnotes\"><h2 id=\"footnote-label\" class=\"sr-only\">Footnotes</h2>\n<ol>\n<li id=\"user-content-fn-a\">\n<p>b <a href=\"#user-content-fnref-a\" data-footnote-backref=\"\" aria-label=\"Back to content\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>\n"
);

// Pass `gfm_footnote_clobber_prefix` to use something else:
assert_eq!(
    to_html_with_options(
        "[^a]\n\n[^a]: b",
        &Options {
            parse: ParseOptions::gfm(),
            compile: CompileOptions {
              gfm_footnote_clobber_prefix: Some("".into()),
              ..CompileOptions::gfm()
            }
        }
    )?,
    "<p><sup><a href=\"#fn-a\" id=\"fnref-a\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\">1</a></sup></p>\n<section data-footnotes=\"\" class=\"footnotes\"><h2 id=\"footnote-label\" class=\"sr-only\">Footnotes</h2>\n<ol>\n<li id=\"fn-a\">\n<p>b <a href=\"#fnref-a\" data-footnote-backref=\"\" aria-label=\"Back to content\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>\n"
);
§gfm_footnote_label_attributes: Option<String>

Attributes to use on the footnote label.

The default value is "class=\"sr-only\"". Change it to show the label and add other attributes.

This label is typically hidden visually (assuming a sr-only CSS class is defined that does that), and thus affects screen readers only. If you do have such a class, but want to show this section to everyone, pass an empty string. You can also add different attributes.

👉 Note: id="footnote-label" is always added, because footnote calls use it with aria-describedby to provide an accessible label.

§Examples

use socketry_markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};

// `"class=\"sr-only\""` is used by default:
assert_eq!(
    to_html_with_options(
        "[^a]\n\n[^a]: b",
        &Options::gfm()
    )?,
    "<p><sup><a href=\"#user-content-fn-a\" id=\"user-content-fnref-a\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\">1</a></sup></p>\n<section data-footnotes=\"\" class=\"footnotes\"><h2 id=\"footnote-label\" class=\"sr-only\">Footnotes</h2>\n<ol>\n<li id=\"user-content-fn-a\">\n<p>b <a href=\"#user-content-fnref-a\" data-footnote-backref=\"\" aria-label=\"Back to content\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>\n"
);

// Pass `gfm_footnote_label_attributes` to use something else:
assert_eq!(
    to_html_with_options(
        "[^a]\n\n[^a]: b",
        &Options {
            parse: ParseOptions::gfm(),
            compile: CompileOptions {
              gfm_footnote_label_attributes: Some("class=\"footnote-heading\"".into()),
              ..CompileOptions::gfm()
            }
        }
    )?,
    "<p><sup><a href=\"#user-content-fn-a\" id=\"user-content-fnref-a\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\">1</a></sup></p>\n<section data-footnotes=\"\" class=\"footnotes\"><h2 id=\"footnote-label\" class=\"footnote-heading\">Footnotes</h2>\n<ol>\n<li id=\"user-content-fn-a\">\n<p>b <a href=\"#user-content-fnref-a\" data-footnote-backref=\"\" aria-label=\"Back to content\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>\n"
);
§gfm_footnote_label_tag_name: Option<String>

HTML tag name to use for the footnote label element.

The default value is "h2". Change it to match your document structure.

This label is typically hidden visually (assuming a sr-only CSS class is defined that does that), and thus affects screen readers only. If you do have such a class, but want to show this section to everyone, pass different attributes with the gfm_footnote_label_attributes option.

§Examples

use socketry_markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};

// `"h2"` is used by default:
assert_eq!(
    to_html_with_options(
        "[^a]\n\n[^a]: b",
        &Options::gfm()
    )?,
    "<p><sup><a href=\"#user-content-fn-a\" id=\"user-content-fnref-a\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\">1</a></sup></p>\n<section data-footnotes=\"\" class=\"footnotes\"><h2 id=\"footnote-label\" class=\"sr-only\">Footnotes</h2>\n<ol>\n<li id=\"user-content-fn-a\">\n<p>b <a href=\"#user-content-fnref-a\" data-footnote-backref=\"\" aria-label=\"Back to content\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>\n"
);

// Pass `gfm_footnote_label_tag_name` to use something else:
assert_eq!(
    to_html_with_options(
        "[^a]\n\n[^a]: b",
        &Options {
            parse: ParseOptions::gfm(),
            compile: CompileOptions {
              gfm_footnote_label_tag_name: Some("h1".into()),
              ..CompileOptions::gfm()
            }
        }
    )?,
    "<p><sup><a href=\"#user-content-fn-a\" id=\"user-content-fnref-a\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\">1</a></sup></p>\n<section data-footnotes=\"\" class=\"footnotes\"><h1 id=\"footnote-label\" class=\"sr-only\">Footnotes</h1>\n<ol>\n<li id=\"user-content-fn-a\">\n<p>b <a href=\"#user-content-fnref-a\" data-footnote-backref=\"\" aria-label=\"Back to content\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>\n"
);
§gfm_footnote_label: Option<String>

Textual label to use for the footnotes section.

The default value is "Footnotes". Change it when the markdown is not in English.

This label is typically hidden visually (assuming a sr-only CSS class is defined that does that), and thus affects screen readers only. If you do have such a class, but want to show this section to everyone, pass different attributes with the gfm_footnote_label_attributes option.

§Examples

use socketry_markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};

// `"Footnotes"` is used by default:
assert_eq!(
    to_html_with_options(
        "[^a]\n\n[^a]: b",
        &Options::gfm()
    )?,
    "<p><sup><a href=\"#user-content-fn-a\" id=\"user-content-fnref-a\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\">1</a></sup></p>\n<section data-footnotes=\"\" class=\"footnotes\"><h2 id=\"footnote-label\" class=\"sr-only\">Footnotes</h2>\n<ol>\n<li id=\"user-content-fn-a\">\n<p>b <a href=\"#user-content-fnref-a\" data-footnote-backref=\"\" aria-label=\"Back to content\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>\n"
);

// Pass `gfm_footnote_label` to use something else:
assert_eq!(
    to_html_with_options(
        "[^a]\n\n[^a]: b",
        &Options {
            parse: ParseOptions::gfm(),
            compile: CompileOptions {
              gfm_footnote_label: Some("Notes de bas de page".into()),
              ..CompileOptions::gfm()
            }
        }
    )?,
    "<p><sup><a href=\"#user-content-fn-a\" id=\"user-content-fnref-a\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\">1</a></sup></p>\n<section data-footnotes=\"\" class=\"footnotes\"><h2 id=\"footnote-label\" class=\"sr-only\">Notes de bas de page</h2>\n<ol>\n<li id=\"user-content-fn-a\">\n<p>b <a href=\"#user-content-fnref-a\" data-footnote-backref=\"\" aria-label=\"Back to content\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>\n"
);
§gfm_task_list_item_checkable: bool

Whether or not GFM task list html <input> items are enabled.

This determines whether or not the user of the browser is able to click and toggle generated checkbox items. The default is false.

§Examples

use socketry_markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};

// With `gfm_task_list_item_checkable`, generated `<input type="checkbox" />`
// tags do not contain the attribute `disabled=""` and are thus toggleable by
// browser users.
assert_eq!(
    to_html_with_options(
        "* [x] y.",
        &Options {
            parse: ParseOptions::gfm(),
            compile: CompileOptions {
                gfm_task_list_item_checkable: true,
                ..CompileOptions::gfm()
            }
        }
    )?,
    "<ul>\n<li><input type=\"checkbox\" checked=\"\" /> y.</li>\n</ul>"
);
§gfm_tagfilter: bool

Whether to support the GFM tagfilter.

This option does nothing if allow_dangerous_html is not turned on. The default is false, which does not apply the GFM tagfilter to HTML. Pass true for output that is a bit closer to GitHub’s actual output.

The tagfilter is kinda weird and kinda useless. The tag filter is a naïve attempt at XSS protection. You should use a proper HTML sanitizing algorithm instead.

§Examples

use socketry_markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};

// With `allow_dangerous_html`, `markdown-rs` passes HTML through untouched:
assert_eq!(
    to_html_with_options(
        "<iframe>",
        &Options {
            parse: ParseOptions::gfm(),
            compile: CompileOptions {
              allow_dangerous_html: true,
              ..CompileOptions::default()
            }
        }
    )?,
    "<iframe>"
);

// Pass `gfm_tagfilter: true` to make some of that safe:
assert_eq!(
    to_html_with_options(
        "<iframe>",
        &Options {
            parse: ParseOptions::gfm(),
            compile: CompileOptions {
              allow_dangerous_html: true,
              gfm_tagfilter: true,
              ..CompileOptions::default()
            }
        }
    )?,
    "&lt;iframe>"
);

§References

§heading_ids: bool

Whether to add unique id attributes to headings for in-page links and tables of contents.

IDs use the same text normalization and duplicate suffixes as mdast::Headings::extract.

The default is false.

Implementations§

Source§

impl CompileOptions

Source

pub fn gfm() -> Self

GFM.

GFM stands for GitHub flavored markdown. On the compilation side, GFM turns on the GFM tag filter. The tagfilter is useless, but it’s included here for consistency, and this method exists for parity to parse options.

For more information, see the GFM specification: https://github.github.com/gfm/.

Trait Implementations§

Source§

impl Clone for CompileOptions

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for CompileOptions

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for CompileOptions

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.