6
6
* @typedef {import('../state.js').State } State
7
7
*/
8
8
9
+ /**
10
+ * @typedef ExtractResult
11
+ * Result of extracting a leading checkbox.
12
+ * @property {Element | undefined } checkbox
13
+ * The checkbox that was removed, if any.
14
+ * @property {Element } rest
15
+ * If there was a leading checkbox, a deep clone of the node w/o the leading
16
+ * checkbox; otherwise a reference to the given, untouched, node.
17
+ */
18
+
9
19
import { phrasing } from 'hast-util-phrasing'
10
20
11
21
/**
@@ -19,15 +29,14 @@ import {phrasing} from 'hast-util-phrasing'
19
29
export function li ( state , node ) {
20
30
// If the list item starts with a checkbox, remove the checkbox and mark the
21
31
// list item as a GFM task list item.
22
- const { cleanNode, checkbox} = extractLeadingCheckbox ( node )
23
- const checked = checkbox && Boolean ( checkbox . properties . checked )
24
-
25
- const spread = spreadout ( cleanNode )
26
- const children = state . toFlow ( state . all ( cleanNode ) )
32
+ const { rest, checkbox} = extractLeadingCheckbox ( node )
33
+ const checked = checkbox ? Boolean ( checkbox . properties . checked ) : null
34
+ const spread = spreadout ( rest )
35
+ const children = state . toFlow ( state . all ( rest ) )
27
36
28
37
/** @type {ListItem } */
29
38
const result = { type : 'listItem' , spread, checked, children}
30
- state . patch ( cleanNode , result )
39
+ state . patch ( node , result )
31
40
return result
32
41
}
33
42
@@ -75,23 +84,36 @@ function spreadout(node) {
75
84
}
76
85
77
86
/**
78
- * If the first bit of content in an element is a checkbox, create a copy of
79
- * the element that does not include the checkbox and return the cleaned up
80
- * copy alongside the checkbox that was removed. If there was no leading
81
- * checkbox, this returns the original element unaltered (not a copy).
87
+ * Extract a leading checkbox from a list item.
88
+ *
89
+ * If there was a leading checkbox, makes a deep clone of the node w/o the
90
+ * leading checkbox; otherwise a reference to the given, untouched, node is
91
+ * given back.
92
+ *
93
+ * So for example:
94
+ *
95
+ * ```html
96
+ * <li><input type="checkbox">Text</li>
97
+ * ```
82
98
*
83
- * This detects trees like:
84
- * `<li><input type="checkbox">Text</li>`
85
- * And returns a tree like:
86
- * `<li>Text</li>`
99
+ * …becomes:
87
100
*
88
- * Or with nesting:
89
- * `<li><p><input type="checkbox">Text</p></li>`
90
- * Which returns a tree like:
91
- * `<li><p>Text</p></li>`
101
+ * ```html
102
+ * <li>Text</li>
103
+ * ```
104
+ *
105
+ * ```html
106
+ * <li><p><input type="checkbox">Text</p></li>
107
+ * ```
108
+ *
109
+ * …becomes:
110
+ *
111
+ * ```html
112
+ * <li><p>Text</p></li>
113
+ * ```
92
114
*
93
115
* @param {Readonly<Element> } node
94
- * @returns {{cleanNode: Element, checkbox: Element | null} }
116
+ * @returns {ExtractResult }
95
117
*/
96
118
function extractLeadingCheckbox ( node ) {
97
119
const head = node . children [ 0 ]
@@ -103,31 +125,25 @@ function extractLeadingCheckbox(node) {
103
125
head . properties &&
104
126
( head . properties . type === 'checkbox' || head . properties . type === 'radio' )
105
127
) {
106
- return {
107
- cleanNode : { ...node , children : node . children . slice ( 1 ) } ,
108
- checkbox : head
109
- }
128
+ const rest = { ...node , children : node . children . slice ( 1 ) }
129
+ return { checkbox : head , rest}
110
130
}
111
131
112
- // The checkbox may be nested in another element. If the first element has
113
- // children, look for a leading checkbox inside it.
132
+ // The checkbox may be nested in another element.
133
+ // If the first element has children, look for a leading checkbox inside it.
114
134
//
115
- // NOTE: this only handles nesting in `<p>` elements, which is most common.
116
- // It' s possible a leading checkbox might be nested in other types of flow or
135
+ // This only handles nesting in `<p>` elements, which is most common.
136
+ // It’ s possible a leading checkbox might be nested in other types of flow or
117
137
// phrasing elements (and *deeply* nested, which is not possible with `<p>`).
118
138
// Limiting things to `<p>` elements keeps this simpler for now.
119
139
if ( head && head . type === 'element' && head . tagName === 'p' ) {
120
- const { cleanNode : cleanHead , checkbox} = extractLeadingCheckbox ( head )
140
+ const { checkbox, rest : restHead } = extractLeadingCheckbox ( head )
141
+
121
142
if ( checkbox ) {
122
- return {
123
- cleanNode : {
124
- ...node ,
125
- children : [ cleanHead , ...node . children . slice ( 1 ) ]
126
- } ,
127
- checkbox
128
- }
143
+ const rest = { ...node , children : [ restHead , ...node . children . slice ( 1 ) ] }
144
+ return { checkbox, rest}
129
145
}
130
146
}
131
147
132
- return { cleanNode : node , checkbox : null }
148
+ return { checkbox : undefined , rest : node }
133
149
}
0 commit comments