|
4 | 4 | * @typedef {import('../state.js').State} State
|
5 | 5 | */
|
6 | 6 |
|
| 7 | +import {phrasing} from 'hast-util-phrasing' |
| 8 | + |
7 | 9 | /**
|
8 | 10 | * @param {State} state
|
9 | 11 | * State.
|
@@ -42,15 +44,56 @@ export function li(state, node) {
|
42 | 44 | }
|
43 | 45 | }
|
44 | 46 |
|
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)) |
46 | 51 |
|
47 | 52 | /** @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) |
55 | 55 | return result
|
56 | 56 | }
|
| 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 | +} |
0 commit comments