|
2 | 2 | * @typedef {import('../types.js').Handle} Handle
|
3 | 3 | * @typedef {import('../types.js').Element} Element
|
4 | 4 | * @typedef {import('../types.js').ElementChild} ElementChild
|
5 |
| - * @typedef {import('../types.js').MdastNode} MdastNode |
6 | 5 | */
|
7 | 6 |
|
8 | 7 | import {convertElement} from 'hast-util-is-element'
|
| 8 | +import {phrasing} from 'hast-util-phrasing' |
9 | 9 | import {wrapChildren} from '../util/wrap-children.js'
|
10 | 10 |
|
11 | 11 | const p = convertElement('p')
|
@@ -45,7 +45,52 @@ export function li(h, node) {
|
45 | 45 | }
|
46 | 46 | }
|
47 | 47 |
|
48 |
| - const content = wrapChildren(h, clone || node) |
| 48 | + if (!clone) clone = node |
49 | 49 |
|
50 |
| - return h(node, 'listItem', {spread: content.length > 1, checked}, content) |
| 50 | + const spread = spreadout(clone) |
| 51 | + const content = wrapChildren(h, clone) |
| 52 | + |
| 53 | + return h(node, 'listItem', {spread, checked}, content) |
| 54 | +} |
| 55 | + |
| 56 | +/** |
| 57 | + * Check if an element should spread out. |
| 58 | + * The reason to spread out a markdown list item is primarily whether writing |
| 59 | + * the equivalent in markdown, would yield a spread out item. |
| 60 | + * |
| 61 | + * A spread out item results in `<p>` and `</p>` tags. |
| 62 | + * Otherwise, the phrasing would be output directly. |
| 63 | + * We can check for that: if there’s a `<p>` element, spread it out. |
| 64 | + * |
| 65 | + * But what if there are no paragraphs? |
| 66 | + * In that case, we can also assume that if two “block” things were written in |
| 67 | + * an item, that it is spread out, because blocks are typically joined by blank |
| 68 | + * lines, which also means a spread item. |
| 69 | + * |
| 70 | + * Lastly, because in HTML things can be wrapped in a `<div>` or similar, we |
| 71 | + * delve into non-phrasing elements here to figure out if they themselves |
| 72 | + * contain paragraphs or 2 or more flow non-phrasing elements. |
| 73 | + * |
| 74 | + * @param {Element} node |
| 75 | + * @returns {boolean} |
| 76 | + */ |
| 77 | +function spreadout(node) { |
| 78 | + let index = -1 |
| 79 | + let seenFlow = false |
| 80 | + |
| 81 | + while (++index < node.children.length) { |
| 82 | + const child = node.children[index] |
| 83 | + |
| 84 | + if (child.type === 'element') { |
| 85 | + if (phrasing(child)) continue |
| 86 | + |
| 87 | + if (child.tagName === 'p' || seenFlow || spreadout(child)) { |
| 88 | + return true |
| 89 | + } |
| 90 | + |
| 91 | + seenFlow = true |
| 92 | + } |
| 93 | + } |
| 94 | + |
| 95 | + return false |
51 | 96 | }
|
0 commit comments