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:
-- First
-- Second
-- Third
+- First
+- Second
+- Third
and:
-- One
-- Two
-- Three
+- One
+- Two
+- Three
Loose using tabs:
-First
-Second
-Third
+First
+Second
+Third
and using spaces:
-One
-Two
-Three
+One
+Two
+Three
Multiple paragraphs:
-Item 1, graf one.
+Item 1, graf one.
Item 2. graf two. The quick brown fox jumped over the lazy dog's
back.
-Item 2.
-Item 3.
+Item 2.
+Item 3.
+
+
+Custom steps:
+
+
+- Two
+- Five
+- Thirteen
Nested
@@ -112,28 +120,28 @@ Nested
Here's another:
-- First
-- Second:
+
- First
+- Second:
-- Third
+- Third
Same thing but with paragraphs:
-First
-Second:
+First
+Second:
-Third
+Third
@@ -146,3 +154,26 @@ Nested
that
+
+Nested custom steps:
+
+- First
+- Second
+
+- Nested fifth
+- Nested seventh
+
+
+- Third
+
+
+Nested custom steps within unordered:
+
+- Foo
+
+- Nested third
+- Nested seventh
+
+
+- Bar
+
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 /- Foo<\/li>/, output
+ assert_equal %{
Foo:
+
+
+- Foo
+- Bar
+
}, 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:
+
+
+- Foo
+- Bar
+
}, output
end
def test_references_with_tabs_after_colon