diff --git a/CHANGELOG.md b/CHANGELOG.md index 145b24dd..df2aaadc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Version 4.0.0 + +* Unobtrusively support the breaking up of ordered lists without resetting their indices/steps. + + Fixes #740. + + *Dennis Hackethal* + ## Version 3.6.0 * Avoid warnings running on Ruby 3.2+. diff --git a/README.markdown b/README.markdown index b9764ba0..f8f34bbc 100644 --- a/README.markdown +++ b/README.markdown @@ -254,7 +254,7 @@ end * header(text, header_level) * hrule() * list(contents, list_type) -* list_item(text, list_type) +* list_item(text, list_type, step) * paragraph(text) * table(header, body) * table_row(content) diff --git a/ext/redcarpet/html.c b/ext/redcarpet/html.c index 3e294054..5479adc2 100644 --- a/ext/redcarpet/html.c +++ b/ext/redcarpet/html.c @@ -404,9 +404,14 @@ rndr_list(struct buf *ob, const struct buf *text, int flags, void *opaque) } static void -rndr_listitem(struct buf *ob, const struct buf *text, int flags, void *opaque) +rndr_listitem(struct buf *ob, const struct buf *text, int flags, void *opaque, int step) { - BUFPUTSL(ob, "
  • "); + if (flags & MKD_LIST_ORDERED) { + bufprintf(ob, "
  • ", step); + } else { + BUFPUTSL(ob, "
  • "); + } + if (text) { size_t size = text->size; while (size && text->data[size - 1] == '\n') diff --git a/ext/redcarpet/markdown.c b/ext/redcarpet/markdown.c index 9a761c58..15300d60 100644 --- a/ext/redcarpet/markdown.c +++ b/ext/redcarpet/markdown.c @@ -1848,6 +1848,24 @@ parse_blockcode(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t return beg; } +/* extract_prefix_number • Extracts '12' from '12. foo' */ +/* Useful for list items of ordered lists */ +static int +extract_prefix_number(uint8_t *data, size_t size) +{ + size_t i = 0; + int prefix_num = 0; + + while (i < size && data[i] == ' ') i++; + + while (i < size && data[i] >= '0' && data[i] <= '9') { + prefix_num = prefix_num * 10 + (data[i] - '0'); + i++; + } + + return prefix_num; +} + /* parse_listitem • parsing of a single list item */ /* assuming initial prefix is already removed */ static size_t @@ -1862,6 +1880,8 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s while (orgpre < 3 && orgpre < size && data[orgpre] == ' ') orgpre++; + int prefix_num = 0; + beg = prefix_uli(data, size); if (!beg) beg = prefix_oli(data, size); @@ -1869,6 +1889,8 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s if (!beg) return 0; + prefix_num = extract_prefix_number(data, size); + /* skipping to the beginning of the following line */ end = beg; while (end < size && data[end - 1] != '\n') @@ -1977,7 +1999,7 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s /* render of li itself */ if (rndr->cb.listitem) - rndr->cb.listitem(ob, inter, *flags, rndr->opaque); + rndr->cb.listitem(ob, inter, *flags, rndr->opaque, prefix_num); rndr_popbuf(rndr, BUFFER_SPAN); rndr_popbuf(rndr, BUFFER_SPAN); diff --git a/ext/redcarpet/markdown.h b/ext/redcarpet/markdown.h index 11818d21..954c8429 100644 --- a/ext/redcarpet/markdown.h +++ b/ext/redcarpet/markdown.h @@ -75,7 +75,7 @@ struct sd_callbacks { void (*header)(struct buf *ob, const struct buf *text, int level, void *opaque); void (*hrule)(struct buf *ob, void *opaque); void (*list)(struct buf *ob, const struct buf *text, int flags, void *opaque); - void (*listitem)(struct buf *ob, const struct buf *text, int flags, void *opaque); + void (*listitem)(struct buf *ob, const struct buf *text, int flags, void *opaque, int step); void (*paragraph)(struct buf *ob, const struct buf *text, void *opaque); void (*table)(struct buf *ob, const struct buf *header, const struct buf *body, void *opaque); void (*table_row)(struct buf *ob, const struct buf *text, void *opaque); diff --git a/ext/redcarpet/rc_render.c b/ext/redcarpet/rc_render.c index 960a1ac8..81930bdf 100644 --- a/ext/redcarpet/rc_render.c +++ b/ext/redcarpet/rc_render.c @@ -86,10 +86,10 @@ rndr_list(struct buf *ob, const struct buf *text, int flags, void *opaque) } static void -rndr_listitem(struct buf *ob, const struct buf *text, int flags, void *opaque) +rndr_listitem(struct buf *ob, const struct buf *text, int flags, void *opaque, int step) { - BLOCK_CALLBACK("list_item", 2, buf2str(text), - (flags & MKD_LIST_ORDERED) ? CSTR2SYM("ordered") : CSTR2SYM("unordered")); + BLOCK_CALLBACK("list_item", 3, buf2str(text), + (flags & MKD_LIST_ORDERED) ? CSTR2SYM("ordered") : CSTR2SYM("unordered"), INT2NUM(step)); } static void diff --git a/lib/redcarpet.rb b/lib/redcarpet.rb index c851da5e..b8767ad1 100644 --- a/lib/redcarpet.rb +++ b/lib/redcarpet.rb @@ -2,7 +2,7 @@ require 'redcarpet/compat' module Redcarpet - VERSION = '3.6.0' + VERSION = '4.0.0' class Markdown attr_reader :renderer diff --git a/lib/redcarpet/render_man.rb b/lib/redcarpet/render_man.rb index 6820fd75..147b56c6 100644 --- a/lib/redcarpet/render_man.rb +++ b/lib/redcarpet/render_man.rb @@ -52,10 +52,10 @@ def list(content, list_type) end end - def list_item(content, list_type) + def list_item(content, list_type, step) case list_type when :ordered - ".IP \\n+[step]\n#{content.strip}\n" + ".IP \\n+[#{step}]\n#{content.strip}\n" when :unordered ".IP \\[bu] 2 \n#{content.strip}\n" end diff --git a/redcarpet.gemspec b/redcarpet.gemspec index 251ad421..ac48ce75 100644 --- a/redcarpet.gemspec +++ b/redcarpet.gemspec @@ -1,10 +1,10 @@ # encoding: utf-8 Gem::Specification.new do |s| s.name = 'redcarpet' - s.version = '3.6.0' + s.version = '4.0.0' s.summary = "Markdown that smells nice" s.description = 'A fast, safe and extensible Markdown to (X)HTML parser' - s.date = '2023-01-29' + s.date = '2023-08-25' s.email = 'vicent@github.com' s.homepage = 'https://github.com/vmg/redcarpet' s.authors = ["Natacha Porté", "Vicent Martí"] diff --git a/test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html b/test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html index ba71eab3..e8895a6c 100644 --- a/test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html +++ b/test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html @@ -57,44 +57,52 @@

    Ordered

    Tight:

      -
    1. First
    2. -
    3. Second
    4. -
    5. Third
    6. +
    7. First
    8. +
    9. Second
    10. +
    11. Third

    and:

      -
    1. One
    2. -
    3. Two
    4. -
    5. Three
    6. +
    7. One
    8. +
    9. Two
    10. +
    11. Three

    Loose using tabs:

      -
    1. First

    2. -
    3. Second

    4. -
    5. Third

    6. +
    7. First

    8. +
    9. Second

    10. +
    11. Third

    and using spaces:

      -
    1. One

    2. -
    3. Two

    4. -
    5. Three

    6. +
    7. One

    8. +
    9. Two

    10. +
    11. Three

    Multiple paragraphs:

      -
    1. Item 1, graf one.

      +
    2. Item 1, graf one.

      Item 2. graf two. The quick brown fox jumped over the lazy dog's back.

    3. -
    4. Item 2.

    5. -
    6. Item 3.

    7. +
    8. Item 2.

    9. +
    10. Item 3.

    11. +
    + +

    Custom steps:

    + +
      +
    1. Two
    2. +
    3. Five
    4. +
    5. Thirteen

    Nested

    @@ -112,28 +120,28 @@

    Nested

    Here's another:

      -
    1. First
    2. -
    3. Second: +
    4. First
    5. +
    6. Second:
      • Fee
      • Fie
      • Foe
    7. -
    8. Third
    9. +
    10. Third

    Same thing but with paragraphs:

      -
    1. First

    2. -
    3. Second:

      +
    4. First

    5. +
    6. Second:

      • Fee
      • Fie
      • Foe
    7. -
    8. Third

    9. +
    10. Third

    @@ -146,3 +154,26 @@

    Nested

    that

  • + +

    Nested custom steps:

    +
      +
    1. First
    2. +
    3. Second +
        +
      1. Nested fifth
      2. +
      3. Nested seventh
      4. +
      +
    4. +
    5. Third
    6. +
    + +

    Nested custom steps within unordered:

    + diff --git a/test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text b/test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text index 7f3b4977..122fed7c 100644 --- a/test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text +++ b/test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text @@ -93,7 +93,11 @@ Multiple paragraphs: 3. Item 3. +Custom steps: +2. Two +5. Five +13. Thirteen ## Nested @@ -129,3 +133,18 @@ This was an error in Markdown 1.0.1: * sub that + +Nested custom steps: + +1. First +2. Second + 5. Nested fifth + 7. Nested seventh +3. Third + +Nested custom steps within unordered: + +* Foo + 3. Nested third + 7. Nested seventh +* Bar diff --git a/test/markdown_test.rb b/test/markdown_test.rb index b1a69564..f3891f3d 100644 --- a/test/markdown_test.rb +++ b/test/markdown_test.rb @@ -398,8 +398,23 @@ def test_char_escaping_when_highlighting def test_ordered_lists_with_lax_spacing output = render("Foo:\n1. Foo\n2. Bar", with: [:lax_spacing]) - assert_match /
      /, output - assert_match /
    1. Foo<\/li>/, output + assert_equal %{

      Foo:

      + +
        +
      1. Foo
      2. +
      3. Bar
      4. +
      }, output + end + + def test_ordered_lists_with_lax_spacing_and_custom_start + output = render("Foo:\n2. Foo\n5. Bar", with: [:lax_spacing]) + + assert_equal %{

      Foo:

      + +
        +
      1. Foo
      2. +
      3. Bar
      4. +
      }, output end def test_references_with_tabs_after_colon