diff --git a/lib/handlers/li.js b/lib/handlers/li.js
index 1784ceb..017a34d 100644
--- a/lib/handlers/li.js
+++ b/lib/handlers/li.js
@@ -4,6 +4,8 @@
* @typedef {import('../state.js').State} State
*/
+import {phrasing} from 'hast-util-phrasing'
+
/**
* @param {State} state
* State.
@@ -42,15 +44,56 @@ export function li(state, node) {
}
}
- const children = state.toFlow(state.all(clone || node))
+ if (!clone) clone = node
+
+ const spread = spreadout(clone)
+ const children = state.toFlow(state.all(clone))
/** @type {ListItem} */
- const result = {
- type: 'listItem',
- spread: children.length > 1,
- checked,
- children
- }
- state.patch(node, result)
+ const result = {type: 'listItem', spread, checked, children}
+ state.patch(clone, result)
return result
}
+
+/**
+ * Check if an element should spread out.
+ *
+ * The reason to spread out a markdown list item is primarily whether writing
+ * the equivalent in markdown, would yield a spread out item.
+ *
+ * A spread out item results in `
` and `
` tags.
+ * Otherwise, the phrasing would be output directly.
+ * We can check for that: if there’s a `` element, spread it out.
+ *
+ * But what if there are no paragraphs?
+ * In that case, we can also assume that if two “block” things were written in
+ * an item, that it is spread out, because blocks are typically joined by blank
+ * lines, which also means a spread item.
+ *
+ * Lastly, because in HTML things can be wrapped in a `
` or similar, we
+ * delve into non-phrasing elements here to figure out if they themselves
+ * contain paragraphs or 2 or more flow non-phrasing elements.
+ *
+ * @param {Element} node
+ * @returns {boolean}
+ */
+function spreadout(node) {
+ let index = -1
+ let seenFlow = false
+
+ while (++index < node.children.length) {
+ const child = node.children[index]
+
+ if (child.type === 'element') {
+ if (phrasing(child)) continue
+
+ if (child.tagName === 'p' || seenFlow || spreadout(child)) {
+ return true
+ }
+
+ seenFlow = true
+ }
+ }
+
+ return false
+}
diff --git a/test/fixtures/dl/index.json b/test/fixtures/dl/index.json
index a875830..fe70035 100644
--- a/test/fixtures/dl/index.json
+++ b/test/fixtures/dl/index.json
@@ -1,3 +1,5 @@
{
+ "": "spread can’t be losslessly translated between HTML <> markdown",
+ "tree": false,
"fragment": true
}
diff --git a/test/fixtures/dl/index.md b/test/fixtures/dl/index.md
index 1150ed7..f538704 100644
--- a/test/fixtures/dl/index.md
+++ b/test/fixtures/dl/index.md
@@ -22,7 +22,9 @@ Charlie.
* Firefox
* A web browser.
+
* A Red Panda.
+
* ```js
charlie();
```
diff --git a/test/fixtures/ol/index.json b/test/fixtures/ol/index.json
index a875830..fe70035 100644
--- a/test/fixtures/ol/index.json
+++ b/test/fixtures/ol/index.json
@@ -1,3 +1,5 @@
{
+ "": "spread can’t be losslessly translated between HTML <> markdown",
+ "tree": false,
"fragment": true
}
diff --git a/test/fixtures/ol/index.md b/test/fixtures/ol/index.md
index 16f435a..6c4b2f6 100644
--- a/test/fixtures/ol/index.md
+++ b/test/fixtures/ol/index.md
@@ -1,5 +1,7 @@
2. Alpha
+
3. Bravo
+
4. ```js
charlie();
```
@@ -27,23 +29,31 @@ Bar.
Baz.
1.
+
2. Something else
Qux.
1. Something else
+
2.
Quux.
1. Something else
+
2.
Quuux.
1. [x] Bravo
+
2. [ ] Charlie
+
3. [x] Delta
+
4. [ ] Echo
+
5. [ ] **Foxtrot**
+
6. [ ] **Golf**
diff --git a/test/fixtures/ul/index.json b/test/fixtures/ul/index.json
index a875830..fe70035 100644
--- a/test/fixtures/ul/index.json
+++ b/test/fixtures/ul/index.json
@@ -1,3 +1,5 @@
{
+ "": "spread can’t be losslessly translated between HTML <> markdown",
+ "tree": false,
"fragment": true
}
diff --git a/test/fixtures/ul/index.md b/test/fixtures/ul/index.md
index cc1d379..490718a 100644
--- a/test/fixtures/ul/index.md
+++ b/test/fixtures/ul/index.md
@@ -1,5 +1,7 @@
* Alpha
+
* Bravo
+
* ```js
charlie();
```
@@ -27,23 +29,31 @@ Bar.
Baz.
*
+
* Something else
Qux.
* Something else
+
*
Quux.
* Something else
+
*
Quuux.
* [x] Bravo
+
* [ ] Charlie
+
* [x] Delta
+
* [ ] Echo
+
* [ ] **Foxtrot**
+
* [ ] **Golf**