diff options
author | Titus Wormer <tituswormer@gmail.com> | 2022-08-25 13:16:45 +0200 |
---|---|---|
committer | Titus Wormer <tituswormer@gmail.com> | 2022-08-25 13:16:45 +0200 |
commit | 1e4c95079cb97b2b02440b21945c6d12741a7d19 (patch) | |
tree | 4f6a4a179e72630c1cdd058f84498e32b9a433e0 /src/lib.rs | |
parent | 49b6a4e72516e8b2a8768e761a60a4f461802d69 (diff) | |
download | markdown-rs-1e4c95079cb97b2b02440b21945c6d12741a7d19.tar.gz markdown-rs-1e4c95079cb97b2b02440b21945c6d12741a7d19.tar.bz2 markdown-rs-1e4c95079cb97b2b02440b21945c6d12741a7d19.zip |
Add support for GFM footnotes
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 254 |
1 files changed, 238 insertions, 16 deletions
@@ -171,7 +171,20 @@ pub struct Constructs { /// ^^^^^^^^^^^^^^^^^^^ /// ``` pub gfm_autolink_literal: bool, - /// GFM: strikethrough. + /// GFM: footnote definition. + /// + /// ```markdown + /// > | [^a]: b + /// ^^^^^^^ + /// ``` + pub gfm_footnote_definition: bool, + /// GFM: footnote label start. + /// + /// ```markdown + /// > | a[^b] + /// ^^ + /// ``` + pub gfm_label_start_footnote: bool, /// /// ```markdown /// > | a ~b~ c. @@ -283,6 +296,8 @@ impl Default for Constructs { definition: true, frontmatter: false, gfm_autolink_literal: false, + gfm_label_start_footnote: false, + gfm_footnote_definition: false, gfm_strikethrough: false, gfm_task_list_item: false, hard_break_escape: true, @@ -308,6 +323,8 @@ impl Constructs { pub fn gfm() -> Self { Self { gfm_autolink_literal: true, + gfm_footnote_definition: true, + gfm_label_start_footnote: true, gfm_strikethrough: true, gfm_task_list_item: true, ..Self::default() @@ -376,6 +393,206 @@ pub struct Options { /// ``` pub allow_dangerous_protocol: bool, + /// Label to use for the footnotes section. + /// + /// Change it when the markdown is not in English. + /// Typically affects screen readers (change `gfm_footnote_label_attributes` + /// to make it visible). + /// + /// ## Examples + /// + /// ``` + /// use micromark::{micromark, micromark_with_options, Options, Constructs}; + /// + /// // `"Footnotes"` is used by default: + /// assert_eq!( + /// micromark_with_options( + /// "[^a]\n\n[^a]: b", + /// &Options { + /// constructs: Constructs::gfm(), + /// ..Options::default() + /// } + /// ), + /// "<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=\"\" class=\"data-footnote-backref\" aria-label=\"Back to content\">↩</a></p>\n</li>\n</ol>\n</section>\n" + /// ); + /// + /// // Pass `gfm_footnote_label` to use something else: + /// assert_eq!( + /// micromark_with_options( + /// "[^a]\n\n[^a]: b", + /// &Options { + /// constructs: Constructs::gfm(), + /// gfm_footnote_label: Some("Notes de bas de page".to_string()), + /// ..Options::default() + /// } + /// ), + /// "<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=\"\" class=\"data-footnote-backref\" aria-label=\"Back to content\">↩</a></p>\n</li>\n</ol>\n</section>\n" + /// ); + /// ``` + pub gfm_footnote_label: Option<String>, + + /// HTML tag to use for the footnote label. + /// + /// Change it to match your document structure and play well with your CSS. + /// + /// ## Examples + /// + /// ``` + /// use micromark::{micromark, micromark_with_options, Options, Constructs}; + /// + /// // `"h2"` is used by default: + /// assert_eq!( + /// micromark_with_options( + /// "[^a]\n\n[^a]: b", + /// &Options { + /// constructs: Constructs::gfm(), + /// ..Options::default() + /// } + /// ), + /// "<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=\"\" class=\"data-footnote-backref\" aria-label=\"Back to content\">↩</a></p>\n</li>\n</ol>\n</section>\n" + /// ); + /// + /// // Pass `gfm_footnote_label_tag_name` to use something else: + /// assert_eq!( + /// micromark_with_options( + /// "[^a]\n\n[^a]: b", + /// &Options { + /// constructs: Constructs::gfm(), + /// gfm_footnote_label_tag_name: Some("h1".to_string()), + /// ..Options::default() + /// } + /// ), + /// "<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=\"\" class=\"data-footnote-backref\" aria-label=\"Back to content\">↩</a></p>\n</li>\n</ol>\n</section>\n" + /// ); + /// ``` + pub gfm_footnote_label_tag_name: Option<String>, + + /// Attributes to use on the footnote label. + /// + /// > 👉 **Note**: `id="footnote-label"` is always added, because footnote + /// > calls use it with `aria-describedby` to provide an accessible label. + /// + /// A `class="sr-only"` is added by default to hide the label from sighted + /// users. + /// Change it to make the label visible, or add other classes or other + /// attributes. + /// + /// ## Examples + /// + /// ``` + /// use micromark::{micromark, micromark_with_options, Options, Constructs}; + /// + /// // `"class=\"sr-only\""` is used by default: + /// assert_eq!( + /// micromark_with_options( + /// "[^a]\n\n[^a]: b", + /// &Options { + /// constructs: Constructs::gfm(), + /// ..Options::default() + /// } + /// ), + /// "<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=\"\" class=\"data-footnote-backref\" aria-label=\"Back to content\">↩</a></p>\n</li>\n</ol>\n</section>\n" + /// ); + /// + /// // Pass `gfm_footnote_label_attributes` to use something else: + /// assert_eq!( + /// micromark_with_options( + /// "[^a]\n\n[^a]: b", + /// &Options { + /// constructs: Constructs::gfm(), + /// gfm_footnote_label_attributes: Some("class=\"footnote-heading\"".to_string()), + /// ..Options::default() + /// } + /// ), + /// "<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=\"\" class=\"data-footnote-backref\" aria-label=\"Back to content\">↩</a></p>\n</li>\n</ol>\n</section>\n" + /// ); + /// ``` + pub gfm_footnote_label_attributes: Option<String>, + + /// Label to use from backreferences back to their footnote call. + /// + /// Change it when the markdown is not in English. + /// Affects screen readers. + /// + /// ## Examples + /// + /// ``` + /// use micromark::{micromark, micromark_with_options, Options, Constructs}; + /// + /// // `"Back to content"` is used by default: + /// assert_eq!( + /// micromark_with_options( + /// "[^a]\n\n[^a]: b", + /// &Options { + /// constructs: Constructs::gfm(), + /// ..Options::default() + /// } + /// ), + /// "<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=\"\" class=\"data-footnote-backref\" aria-label=\"Back to content\">↩</a></p>\n</li>\n</ol>\n</section>\n" + /// ); + /// + /// // Pass `gfm_footnote_back_label` to use something else: + /// assert_eq!( + /// micromark_with_options( + /// "[^a]\n\n[^a]: b", + /// &Options { + /// constructs: Constructs::gfm(), + /// gfm_footnote_back_label: Some("Arrière".to_string()), + /// ..Options::default() + /// } + /// ), + /// "<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=\"\" class=\"data-footnote-backref\" aria-label=\"Arrière\">↩</a></p>\n</li>\n</ol>\n</section>\n" + /// ); + /// ``` + pub gfm_footnote_back_label: Option<String>, + + /// Prefix to use before the `id` attribute on footnotes to prevent them + /// from *clobbering*. + /// + /// DOM clobbering is this: + /// + /// ```html + /// <p id=x></p> + /// <script>alert(x) // `x` now refers to the DOM `p#x` element</script> + /// ``` + /// + /// The above example shows that elements are made available by browsers, + /// by their ID, on the `window` object, which is a security risk because + /// you might be expecting some other variable at that place. + /// Using a prefix solves this problem. + /// + /// ## Examples + /// + /// ``` + /// use micromark::{micromark, micromark_with_options, Options, Constructs}; + /// + /// // `"user-content-"` is used by default: + /// assert_eq!( + /// micromark_with_options( + /// "[^a]\n\n[^a]: b", + /// &Options { + /// constructs: Constructs::gfm(), + /// ..Options::default() + /// } + /// ), + /// "<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=\"\" class=\"data-footnote-backref\" aria-label=\"Back to content\">↩</a></p>\n</li>\n</ol>\n</section>\n" + /// ); + /// + /// // Pass `gfm_footnote_clobber_prefix` to use something else: + /// assert_eq!( + /// micromark_with_options( + /// "[^a]\n\n[^a]: b", + /// &Options { + /// constructs: Constructs::gfm(), + /// gfm_footnote_clobber_prefix: Some("".to_string()), + /// ..Options::default() + /// } + /// ), + /// "<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=\"\" class=\"data-footnote-backref\" aria-label=\"Back to content\">↩</a></p>\n</li>\n</ol>\n</section>\n" + /// ); + /// ``` + pub gfm_footnote_clobber_prefix: Option<String>, + /// Whether to support GFM strikethrough (if enabled in `constructs`) with /// a single tilde (default: true). /// @@ -389,26 +606,26 @@ pub struct Options { /// // micromark supports single tildes by default: /// assert_eq!( /// micromark_with_options( - /// "~a~", - /// &Options { - /// constructs: Constructs::gfm(), - /// ..Options::default() - /// } - /// ), - /// "<p><del>a</del></p>" + /// "~a~", + /// &Options { + /// constructs: Constructs::gfm(), + /// ..Options::default() + /// } + /// ), + /// "<p><del>a</del></p>" /// ); /// /// // Pass `gfm_strikethrough_single_tilde: false` to turn that off: /// assert_eq!( /// micromark_with_options( - /// "~a~", - /// &Options { - /// constructs: Constructs::gfm(), - /// gfm_strikethrough_single_tilde: false, - /// ..Options::default() - /// } - /// ), - /// "<p>~a~</p>" + /// "~a~", + /// &Options { + /// constructs: Constructs::gfm(), + /// gfm_strikethrough_single_tilde: false, + /// ..Options::default() + /// } + /// ), + /// "<p>~a~</p>" /// ); /// ``` pub gfm_strikethrough_single_tilde: bool, @@ -488,6 +705,11 @@ impl Default for Options { Self { allow_dangerous_html: false, allow_dangerous_protocol: false, + gfm_footnote_label: None, + gfm_footnote_label_tag_name: None, + gfm_footnote_label_attributes: None, + gfm_footnote_back_label: None, + gfm_footnote_clobber_prefix: None, gfm_strikethrough_single_tilde: true, default_line_ending: LineEnding::default(), constructs: Constructs::default(), |