Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unobtrusively support the breaking up of ordered lists without resetting their indices/steps #741

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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+.
Expand Down
2 changes: 1 addition & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 7 additions & 2 deletions ext/redcarpet/html.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, "<li>");
if (flags & MKD_LIST_ORDERED) {
bufprintf(ob, "<li data-step=\"%d\">", step);
} else {
BUFPUTSL(ob, "<li>");
}

if (text) {
size_t size = text->size;
while (size && text->data[size - 1] == '\n')
Expand Down
24 changes: 23 additions & 1 deletion ext/redcarpet/markdown.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -1862,13 +1880,17 @@ 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);

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')
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion ext/redcarpet/markdown.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions ext/redcarpet/rc_render.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/redcarpet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
require 'redcarpet/compat'

module Redcarpet
VERSION = '3.6.0'
VERSION = '4.0.0'

class Markdown
attr_reader :renderer
Expand Down
4 changes: 2 additions & 2 deletions lib/redcarpet/render_man.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions redcarpet.gemspec
Original file line number Diff line number Diff line change
@@ -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í"]
Expand Down
73 changes: 52 additions & 21 deletions test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,44 +57,52 @@ <h2>Ordered</h2>
<p>Tight:</p>

<ol>
<li>First</li>
<li>Second</li>
<li>Third</li>
<li data-step="1">First</li>
<li data-step="2">Second</li>
<li data-step="3">Third</li>
</ol>

<p>and:</p>

<ol>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li data-step="1">One</li>
<li data-step="2">Two</li>
<li data-step="3">Three</li>
</ol>

<p>Loose using tabs:</p>

<ol>
<li><p>First</p></li>
<li><p>Second</p></li>
<li><p>Third</p></li>
<li data-step="1"><p>First</p></li>
<li data-step="2"><p>Second</p></li>
<li data-step="3"><p>Third</p></li>
</ol>

<p>and using spaces:</p>

<ol>
<li><p>One</p></li>
<li><p>Two</p></li>
<li><p>Three</p></li>
<li data-step="1"><p>One</p></li>
<li data-step="2"><p>Two</p></li>
<li data-step="3"><p>Three</p></li>
</ol>

<p>Multiple paragraphs:</p>

<ol>
<li><p>Item 1, graf one.</p>
<li data-step="1"><p>Item 1, graf one.</p>

<p>Item 2. graf two. The quick brown fox jumped over the lazy dog's
back.</p></li>
<li><p>Item 2.</p></li>
<li><p>Item 3.</p></li>
<li data-step="2"><p>Item 2.</p></li>
<li data-step="3"><p>Item 3.</p></li>
</ol>

<p>Custom steps:</p>

<ol>
<li data-step="2">Two</li>
<li data-step="5">Five</li>
<li data-step="13">Thirteen</li>
</ol>

<h2>Nested</h2>
Expand All @@ -112,28 +120,28 @@ <h2>Nested</h2>
<p>Here's another:</p>

<ol>
<li>First</li>
<li>Second:
<li data-step="1">First</li>
<li data-step="2">Second:
<ul>
<li>Fee</li>
<li>Fie</li>
<li>Foe</li>
</ul></li>
<li>Third</li>
<li data-step="3">Third</li>
</ol>

<p>Same thing but with paragraphs:</p>

<ol>
<li><p>First</p></li>
<li><p>Second:</p>
<li data-step="1"><p>First</p></li>
<li data-step="2"><p>Second:</p>

<ul>
<li>Fee</li>
<li>Fie</li>
<li>Foe</li>
</ul></li>
<li><p>Third</p></li>
<li data-step="3"><p>Third</p></li>
</ol>


Expand All @@ -146,3 +154,26 @@ <h2>Nested</h2>

<p>that</p></li>
</ul>

<p>Nested custom steps:</p>
<ol>
<li data-step="1">First</li>
<li data-step="2">Second
<ol>
<li data-step="5">Nested fifth</li>
<li data-step="7">Nested seventh</li>
</ol>
</li>
<li data-step="3">Third</li>
</ol>

<p>Nested custom steps within unordered:</p>
<ul>
<li>Foo
<ol>
<li data-step="3">Nested third</li>
<li data-step="7">Nested seventh</li>
</ol>
</li>
<li>Bar</li>
</ul>
19 changes: 19 additions & 0 deletions test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,11 @@ Multiple paragraphs:

3. Item 3.

Custom steps:

2. Two
5. Five
13. Thirteen

## Nested

Expand Down Expand Up @@ -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
19 changes: 17 additions & 2 deletions test/markdown_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 /<ol>/, output
assert_match /<li>Foo<\/li>/, output
assert_equal %{<p>Foo:</p>

<ol>
<li data-step="1">Foo</li>
<li data-step="2">Bar</li>
</ol>}, output
end

def test_ordered_lists_with_lax_spacing_and_custom_start
output = render("Foo:\n2. Foo\n5. Bar", with: [:lax_spacing])

assert_equal %{<p>Foo:</p>

<ol>
<li data-step="2">Foo</li>
<li data-step="5">Bar</li>
</ol>}, output
end

def test_references_with_tabs_after_colon
Expand Down