Skip to content

Commit 9706341

Browse files
wooormTRIAEIOU
andcommitted
Add improved spread algorithm for list items
Closes GH-75. Closes GH-76. Co-authored-by: TRIAEIOU <94647023+TRIAEIOU@users.noreply.github.com>
1 parent 7a09ded commit 9706341

File tree

7 files changed

+79
-8
lines changed

7 files changed

+79
-8
lines changed

lib/handlers/li.js

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* @typedef {import('../state.js').State} State
55
*/
66

7+
import {phrasing} from 'hast-util-phrasing'
8+
79
/**
810
* @param {State} state
911
* State.
@@ -42,15 +44,56 @@ export function li(state, node) {
4244
}
4345
}
4446

45-
const children = state.toFlow(state.all(clone || node))
47+
if (!clone) clone = node
48+
49+
const spread = spreadout(clone)
50+
const children = state.toFlow(state.all(clone))
4651

4752
/** @type {ListItem} */
48-
const result = {
49-
type: 'listItem',
50-
spread: children.length > 1,
51-
checked,
52-
children
53-
}
54-
state.patch(node, result)
53+
const result = {type: 'listItem', spread, checked, children}
54+
state.patch(clone, result)
5555
return result
5656
}
57+
58+
/**
59+
* Check if an element should spread out.
60+
*
61+
* The reason to spread out a markdown list item is primarily whether writing
62+
* the equivalent in markdown, would yield a spread out item.
63+
*
64+
* A spread out item results in `<p>` and `</p>` tags.
65+
* Otherwise, the phrasing would be output directly.
66+
* We can check for that: if there’s a `<p>` element, spread it out.
67+
*
68+
* But what if there are no paragraphs?
69+
* In that case, we can also assume that if two “block” things were written in
70+
* an item, that it is spread out, because blocks are typically joined by blank
71+
* lines, which also means a spread item.
72+
*
73+
* Lastly, because in HTML things can be wrapped in a `<div>` or similar, we
74+
* delve into non-phrasing elements here to figure out if they themselves
75+
* contain paragraphs or 2 or more flow non-phrasing elements.
76+
*
77+
* @param {Element} node
78+
* @returns {boolean}
79+
*/
80+
function spreadout(node) {
81+
let index = -1
82+
let seenFlow = false
83+
84+
while (++index < node.children.length) {
85+
const child = node.children[index]
86+
87+
if (child.type === 'element') {
88+
if (phrasing(child)) continue
89+
90+
if (child.tagName === 'p' || seenFlow || spreadout(child)) {
91+
return true
92+
}
93+
94+
seenFlow = true
95+
}
96+
}
97+
98+
return false
99+
}

test/fixtures/dl/index.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
{
2+
"": "spread can’t be losslessly translated between HTML <> markdown",
3+
"tree": false,
24
"fragment": true
35
}

test/fixtures/dl/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ Charlie.
2222
* Firefox
2323

2424
* A web browser.
25+
2526
* A Red Panda.
27+
2628
* ```js
2729
charlie();
2830
```

test/fixtures/ol/index.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
{
2+
"": "spread can’t be losslessly translated between HTML <> markdown",
3+
"tree": false,
24
"fragment": true
35
}

test/fixtures/ol/index.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
2. Alpha
2+
23
3. Bravo
4+
35
4. ```js
46
charlie();
57
```
@@ -27,23 +29,31 @@ Bar.
2729
Baz.
2830

2931
1.
32+
3033
2. Something else
3134

3235
Qux.
3336

3437
1. Something else
38+
3539
2.
3640

3741
Quux.
3842

3943
1. Something else
44+
4045
2.
4146

4247
Quuux.
4348

4449
1. [x] Bravo
50+
4551
2. [ ] Charlie
52+
4653
3. [x] Delta
54+
4755
4. [ ] Echo
56+
4857
5. [ ] **Foxtrot**
58+
4959
6. [ ] **Golf**

test/fixtures/ul/index.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
{
2+
"": "spread can’t be losslessly translated between HTML <> markdown",
3+
"tree": false,
24
"fragment": true
35
}

test/fixtures/ul/index.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
* Alpha
2+
23
* Bravo
4+
35
* ```js
46
charlie();
57
```
@@ -27,23 +29,31 @@ Bar.
2729
Baz.
2830

2931
*
32+
3033
* Something else
3134

3235
Qux.
3336

3437
* Something else
38+
3539
*
3640

3741
Quux.
3842

3943
* Something else
44+
4045
*
4146

4247
Quuux.
4348

4449
* [x] Bravo
50+
4551
* [ ] Charlie
52+
4653
* [x] Delta
54+
4755
* [ ] Echo
56+
4857
* [ ] **Foxtrot**
58+
4959
* [ ] **Golf**

0 commit comments

Comments
 (0)