-
-
Notifications
You must be signed in to change notification settings - Fork 16
Description
Initial checklist
- I read the support docs
- I read the contributing guide
- I agree to follow the code of conduct
- I searched issues and couldn’t find anything (or linked relevant results below)
Affected packages and versions
Link to runnable example
No response
Steps to reproduce
Tasklists (lists where each item starts with a checkbox) are parsed correctly if the leading checkbox <input>
element in an <li>
node is nested in a <p>
node, but not if the <input>
is a direct child of the <li>
. I’m not sure why this is a requirement (it’s certainly not in the HTML spec: https://html.spec.whatwg.org/multipage/grouping-content.html#the-li-element), so I assume it’s a bug. (But I appreciate also handling this common case where things are in a paragraph in the list item, which is best practice HTML.)
You can see where this explicit check for a <p>
is implemented in lib/handlers/li.js
:
hast-util-to-mdast/lib/handlers/li.js
Lines 19 to 46 in 7deea1b
export function li(state, node) { | |
const head = node.children[0] | |
/** @type {boolean | null} */ | |
let checked = null | |
/** @type {Element | undefined} */ | |
let clone | |
// Check if this node starts with a checkbox. | |
if (head && head.type === 'element' && head.tagName === 'p') { | |
const checkbox = head.children[0] | |
if ( | |
checkbox && | |
checkbox.type === 'element' && | |
checkbox.tagName === 'input' && | |
checkbox.properties && | |
(checkbox.properties.type === 'checkbox' || | |
checkbox.properties.type === 'radio') | |
) { | |
checked = Boolean(checkbox.properties.checked) | |
clone = { | |
...node, | |
children: [ | |
{...head, children: head.children.slice(1)}, | |
...node.children.slice(1) | |
] | |
} | |
} |
I used this script to test:
import {inspect} from 'node:util';
import {toMdast} from 'hast-util-to-mdast';
const mdast = toMdast(hastTree);
console.log(inspect(mdast, false, 100, true));
Expected behavior
I expected that this script:
import {inspect} from 'node:util';
import {toMdast} from 'hast-util-to-mdast';
const mdast = toMdast({
type: 'root',
children: [
{
type: 'element',
tagName: 'ul',
children: [
{
type: 'element',
tagName: 'li',
children: [
{
type: 'element',
tagName: 'input',
properties: { type: 'checkbox', checked: true }
},
{
type: 'text',
value: 'Checked'
}
]
},
{
type: 'element',
tagName: 'li',
children: [
{
type: 'element',
tagName: 'input',
properties: { type: 'checkbox', checked: false }
},
{
type: 'text',
value: 'Unhecked'
}
]
}
]
}
]
});
console.log(inspect(mdast, false, 100, true));
…to output:
{
type: 'root',
children: [
{
type: 'list',
ordered: false,
start: null,
spread: false,
children: [
{
type: 'listItem',
spread: false,
checked: true,
children: [
{
type: 'paragraph',
children: [ { type: 'text', value: 'Checked' } ]
}
]
},
{
type: 'listItem',
spread: false,
checked: false,
children: [
{
type: 'paragraph',
children: [ { type: 'text', value: 'Unhecked' } ]
}
]
}
]
}
]
}
…which corresponds to this Markdown:
- [x] Checked
- [ ] Unchecked
Actual behavior
Instead, the above script outputs:
{
type: 'root',
children: [
{
type: 'list',
ordered: false,
start: null,
spread: false,
children: [
{
type: 'listItem',
spread: false,
checked: null,
children: [
{
type: 'paragraph',
children: [ { type: 'text', value: '[x]Checked' } ]
}
]
},
{
type: 'listItem',
spread: false,
checked: null,
children: [
{
type: 'paragraph',
children: [ { type: 'text', value: '[ ]Unhecked' } ]
}
]
}
]
}
]
}
…which corresponds to this Markdown:
- \[x]Checked
- \[ ]Unchecked
Instead, to get the expected output, you. need to do:
import {inspect} from 'node:util';
import {toMdast} from 'hast-util-to-mdast';
const mdast = toMdast({
type: 'root',
children: [
{
type: 'element',
tagName: 'ul',
children: [
{
type: 'element',
tagName: 'li',
children: [
{
type: 'element',
tagName: 'p',
children: [
{
type: 'element',
tagName: 'input',
properties: { type: 'checkbox', checked: true }
},
{
type: 'text',
value: 'Checked'
}
]
}
]
},
{
type: 'element',
tagName: 'li',
children: [
{
type: 'element',
tagName: 'p',
children: [
{
type: 'element',
tagName: 'input',
properties: { type: 'checkbox', checked: false }
},
{
type: 'text',
value: 'Unhecked'
}
]
}
]
}
]
}
]
});
console.log(inspect(mdast, false, 100, true));
Affected runtime and version
node>=16
Affected package manager and version
Affected OS and version
macOS 13.5
Build and bundle tools
No response