Skip to content

Commit

Permalink
support more list style types (#17)
Browse files Browse the repository at this point in the history
support more list style types
  • Loading branch information
as-op authored Jan 27, 2025
1 parent 3ca9533 commit 0bd488f
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 29 deletions.
9 changes: 8 additions & 1 deletion demo/demo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,17 @@ ordered_list_point:

ordered_list_point_3:
template: '<number>)'
alphabetical: true
list_style_type: lower-roman

ordered_list_point_4:
template: '(<number>)'
list_style_type: lower-latin

ordered_list_point_5:
list_style_type: upper-latin

ordered_list_point_6:
list_style_type: upper-roman

hrule:
margin_top: 2mm
Expand Down
8 changes: 5 additions & 3 deletions docs/STYLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -496,15 +496,16 @@ Example:
```yml
ordered_list_point:
template: "<number>."
alphabetical: false
list_style_type: decimal
spacing: 0.75mm
spanning: true
```

| Key | Description | Data type |
| - | - | - |
| `spacing` | A number >= 0 and an optional unit<br/>Examples: `10mm`, `10` | number or string<br/>See [Units](#units) |
| `alphabetical` | **Alphabetical bullet points**<br/>Convert the list item number into a character, eg. `a.` `b.` `c.` | boolean |
| `alphabetical` | **Alphabetical bullet points**<br/>(deprecated; use list_style_type) Convert the list item number into a character, eg. `a.` `b.` `c.` | boolean |
| `list_style_type` | **List style type**<br/>The style of the list bullet points, eg. `decimal`, `lower-latin`, `upper-roman`<br/>Valid values:<br/>`decimal`, `lower-latin`, `lower-roman`, `upper-latin`, `upper-roman` | string |
| `spanning` | **Spanning**<br/>Use the width of the largest bullet as indention. | boolean |
| `template` | **Template**<br/>customize what the prefix should contain, eg. `(<number>)` | string |
| … | See [Font properties](#font-properties) | |
Expand All @@ -516,7 +517,8 @@ Key: `ordered_list_point_x`
| Key | Description | Data type |
| - | - | - |
| `spacing` | A number >= 0 and an optional unit<br/>Examples: `10mm`, `10` | number or string<br/>See [Units](#units) |
| `alphabetical` | **Alphabetical bullet points**<br/>Convert the list item number into a character, eg. `a.` `b.` `c.` | boolean |
| `alphabetical` | **Alphabetical bullet points**<br/>(deprecated; use list_style_type) Convert the list item number into a character, eg. `a.` `b.` `c.` | boolean |
| `list_style_type` | **List style type**<br/>The style of the list bullet points, eg. `decimal`, `lower-latin`, `upper-roman`<br/>Valid values:<br/>`decimal`, `lower-latin`, `lower-roman`, `upper-latin`, `upper-roman` | string |
| `spanning` | **Spanning**<br/>Use the width of the largest bullet as indention. | boolean |
| `template` | **Template**<br/>customize what the prefix should contain, eg. `(<number>)` | string |
| … | See [Font properties](#font-properties) | |
Expand Down
41 changes: 39 additions & 2 deletions lib/md_to_pdf/style/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,55 @@ def opt_list_point_sign(style)
(style[:sign] || '•').to_s
end

def list_point_alphabetically(int)
def list_point_latin(int)
name = 'a'
(int - 1).times { name.succ! }
name
end

def list_point_roman(int)
symbols = { 0 => %w[I V], 1 => %w[X L], 2 => %w[C D], 3 => ["M"] }
reversed_digits = int.to_s.chars.reverse
romans = []
reversed_digits.length.times do |i|
romans << if reversed_digits[i].to_i < 4
(symbols[i][0] * reversed_digits[i].to_i)
elsif reversed_digits[i].to_i == 4
(symbols[i][0] + symbols[i][1])
elsif reversed_digits[i].to_i == 9
(symbols[i][0] + symbols[i + 1][0])
else
(symbols[i][1] + (symbols[i][0] * (reversed_digits[i].to_i - 5)))
end
end
romans.reverse.join
end

def opt_list_point_number(number, style)
bullet = opt_list_point_alphabetical?(style) ? list_point_alphabetically(number) : number
bullet = opt_list_point_bullet(number, style)
template = opt_list_point_template(style)
template.gsub('<number>', bullet.to_s)
end

def opt_list_point_bullet(number, style)
list_style_type = style[:list_style_type] || 'decimal'
list_style_type = 'lower-latin' if opt_list_point_alphabetical?(style) # TODO: option is deprecated

case list_style_type
when 'lower-latin'
list_point_latin(number)
when 'upper-latin'
list_point_latin(number).upcase
when 'lower-roman'
list_point_roman(number).downcase
when 'upper-roman'
list_point_roman(number)
else
# decimal
number
end
end

def opt_list_point_alphabetical?(style)
style[:alphabetical] == true
end
Expand Down
16 changes: 14 additions & 2 deletions lib/md_to_pdf/style/schema_styles.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@
"x-example": {
"ordered_list_point": {
"template": "<number>.",
"alphabetical": false,
"list_style_type": "decimal",
"spacing": "0.75mm",
"spanning": true
}
Expand Down Expand Up @@ -915,9 +915,21 @@
},
"alphabetical": {
"title": "Alphabetical bullet points",
"description": "Convert the list item number into a character, eg. `a.` `b.` `c.`",
"description": "(deprecated; use list_style_type) Convert the list item number into a character, eg. `a.` `b.` `c.`",
"type": "boolean"
},
"list_style_type": {
"title": "List style type",
"description": "The style of the list bullet points, eg. `decimal`, `lower-latin`, `upper-roman`",
"type": "string",
"enum": [
"decimal",
"lower-latin",
"lower-roman",
"upper-latin",
"upper-roman"
]
},
"spanning": {
"title": "Spanning",
"description": "Use the width of the largest bullet as indention.",
Expand Down
20 changes: 16 additions & 4 deletions spec/fixtures/list/ordered_custom.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
1. Level 1
1. Level 2
1. Level 1 uses list-style decimal
1. Level 2 { template: "\<number\>)", list_style_type: "decimal" }
2. Level 2
1. Level 3 uses alphabetical points
1. Level 3 { list_style_type: "lower-latin" }
2. Level 3
3. Level 3
1. Level 4 uses a brackets template
4. Level 3
1. Level 4 { template: "(\<number\>)", list_style_type: "lower-roman", spanning: true }
2. Level 4
3. Level 4
4. Level 4
1. Level 5 { list_style_type: "upper-latin" }
2. Level 5
3. Level 5
4. Level 5
5. Level 5
1. Level 6 { list_style_type: "upper-roman" }
2. Level 6
3. Level 6
4. Level 6
5. Level 6
105 changes: 88 additions & 17 deletions spec/markdown_to_pdf/list_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

describe MarkdownToPDF::List do
include_context 'with pdf'
include MarkdownToPDF::StyleHelper

it 'creates an unordered list' do
generator.parse_file('list/unordered.md')
Expand Down Expand Up @@ -77,31 +78,101 @@
{ x: 56.016, y: 705.768, text: "fourteen" }])
end

it 'translates to roman numerals' do
[
['', 0],
['I', 1],
['II', 2],
['III', 3],
['IV', 4],
['V', 5],
['VI', 6],
['VII', 7],
['VIII', 8],
['IX', 9],
['X', 10],
['XI', 11],
['XII', 12],
['XIII', 13],
['XIV', 14],
['XV', 15],
['XVI', 16],
['XX', 20],
['XXX', 30],
['XL', 40],
['L', 50],
['LX', 60],
['LXX', 70],
['LXXX', 80],
['XC', 90],
['XCIX', 99],
['C', 100],
['CC', 200],
['CCC', 300],
['CD', 400],
['D', 500],
['DC', 600],
['CM', 900],
['M', 1000],
['MM', 2000],
['MMIII', 2003]
].each do |roman, arabic|
expect(list_point_roman(arabic)).to eq(roman)
end
end

it 'creates a ordered list with custom bullets' do
styling = {
ordered_list_point_3: { template: '<number>)', alphabetical: true },
ordered_list_point_4: { template: '(<number>)' }
ordered_list_point_2: { template: '<number>)', list_style_type: 'decimal' },
ordered_list_point_3: { list_style_type: 'lower-latin' },
ordered_list_point_4: { template: '(<number>)', list_style_type: 'lower-roman', spanning: true },
ordered_list_point_5: { list_style_type: 'upper-latin' },
ordered_list_point_6: { list_style_type: 'upper-roman' }
}
generator.parse_file('list/ordered_custom.md', styling)
expect_pdf([
{ x: 36.0, y: 747.384, text: "1." },
{ x: 49.344, y: 747.384, text: "Level 1" },
{ x: 49.344, y: 733.512, text: "1." },
{ x: 62.688, y: 733.512, text: "Level 2" },
{ x: 49.344, y: 719.64, text: "2." },
{ x: 62.688, y: 719.64, text: "Level 2" },
{ x: 62.688, y: 705.768, text: "a)" },
{ x: 76.692, y: 705.768, text: "Level 3 uses alphabetical points" },
{ x: 62.688, y: 691.896, text: "b)" },
{ x: 49.344, y: 747.384, text: "Level 1 uses list-style decimal" },
{ x: 49.344, y: 733.512, text: "1)" },
{ x: 63.348, y: 733.512, text: "Level 2 { template: “<number>)”, list_style_type: “decimal” }" },
{ x: 49.344, y: 719.64, text: "2)" },
{ x: 63.348, y: 719.64, text: "Level 2" },
{ x: 63.348, y: 705.768, text: "a." },
{ x: 76.692, y: 705.768, text: "Level 3 { list_style_type: “lower-latin” }" },
{ x: 63.348, y: 691.896, text: "b." },
{ x: 76.692, y: 691.896, text: "Level 3" },
{ x: 62.688, y: 678.024, text: "c)" },
{ x: 63.348, y: 678.024, text: "c." },
{ x: 76.02, y: 678.024, text: "Level 3" },
{ x: 76.02, y: 664.152, text: "(1)" },
{ x: 94.02, y: 664.152, text: "Level 4 uses a brackets template" },
{ x: 76.02, y: 650.28, text: "(2)" },
{ x: 94.02, y: 650.28, text: "Level 4" },
{ x: 76.02, y: 636.408, text: "(3)" },
{ x: 94.02, y: 636.408, text: "Level 4" }])
{ x: 63.348, y: 664.152, text: "d." },
{ x: 76.692, y: 664.152, text: "Level 3" },
{ x: 76.692, y: 650.28, text: "(i)" },
{ x: 96.684, y: 650.28, text: "Level 4 { template: “(<number>)”, list_style_type: “lower-roman”, spanning: true }" },
{ x: 76.692, y: 636.408, text: "(ii)" },
{ x: 96.684, y: 636.408, text: "Level 4" },
{ x: 76.692, y: 622.536, text: "(iii)" },
{ x: 96.684, y: 622.536, text: "Level 4" },
{ x: 76.692, y: 608.664, text: "(iv)" },
{ x: 96.684, y: 608.664, text: "Level 4" },
{ x: 96.684, y: 594.792, text: "A." },
{ x: 111.36, y: 594.792, text: "Level 5 { list_style_type: “upper-latin” }" },
{ x: 96.684, y: 580.92, text: "B." },
{ x: 111.36, y: 580.92, text: "Level 5" },
{ x: 96.684, y: 567.048, text: "C." },
{ x: 112.02, y: 567.048, text: "Level 5" },
{ x: 96.684, y: 553.176, text: "D." },
{ x: 112.02, y: 553.176, text: "Level 5" },
{ x: 96.684, y: 539.304, text: "E." },
{ x: 111.36, y: 539.304, text: "Level 5" },
{ x: 111.36, y: 525.432, text: "I." },
{ x: 121.368, y: 525.432, text: "Level 6 { list_style_type: “upper-roman” }" },
{ x: 111.36, y: 511.56, text: "II." },
{ x: 124.704, y: 511.56, text: "Level 6" },
{ x: 111.36, y: 497.688, text: "III." },
{ x: 128.04, y: 497.688, text: "Level 6" },
{ x: 111.36, y: 483.816, text: "IV." },
{ x: 129.372, y: 483.816, text: "Level 6" },
{ x: 111.36, y: 469.944, text: "V." },
{ x: 126.036, y: 469.944, text: "Level 6" }])
end

it 'creates a tasklist' do
Expand Down

0 comments on commit 0bd488f

Please sign in to comment.