Skip to content

Commit dfcadc3

Browse files
committed
handle nested section-creating elements correctly in SectionParser
1 parent 4bcbec6 commit dfcadc3

File tree

2 files changed

+47
-30
lines changed

2 files changed

+47
-30
lines changed

src/js/parsers/section.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,13 @@ class SectionParser {
109109
let isNodeFinished = false;
110110
let env = {
111111
addSection: (section) => {
112-
this._closeCurrentSection();
112+
// avoid creating empty paragraphs due to wrapper elements around
113+
// parser-plugin-handled elements
114+
if (this.state.section.isMarkerable && !this.state.text) {
115+
this.state.section = null;
116+
} else {
117+
this._closeCurrentSection();
118+
}
113119
this.sections.push(section);
114120
},
115121
addMarkerable: (marker) => {
@@ -148,6 +154,33 @@ class SectionParser {
148154
return;
149155
}
150156

157+
// handle closing the current section and starting a new one if we hit a
158+
// new-section-creating element
159+
if (this.state.section && !this.state.section.isListItem && !isTextNode(node) && node.tagName) {
160+
// handle lists nested inside wrappers
161+
if (this.state.section.isListSection) {
162+
this.parseListItems(node.childNodes);
163+
return;
164+
}
165+
166+
let tagName = normalizeTagName(node.tagName);
167+
if (contains(VALID_MARKUP_SECTION_TAGNAMES, tagName) || contains(VALID_LIST_SECTION_TAGNAMES, tagName)) {
168+
// avoid creating empty paragraphs due to wrappers elements around
169+
// section-creating elements
170+
if (this.state.section.isMarkerable && !this.state.text) {
171+
this.state.section = null;
172+
} else {
173+
this._closeCurrentSection();
174+
}
175+
this._updateStateFromElement(node);
176+
177+
if (this.state.section.isListSection) {
178+
this.parseListItems(node.childNodes);
179+
return;
180+
}
181+
}
182+
}
183+
151184
switch (node.nodeType) {
152185
case NODE_TYPES.TEXT:
153186
this.parseTextNode(node);

tests/unit/parsers/section-test.js

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -225,35 +225,6 @@ test("#parse handles multiple headers in list item", assert => {
225225
});
226226

227227
// see https://github.com/bustle/mobiledoc-kit/issues/656
228-
//
229-
// this is a minimal example of markup that was causing errors when copy/pasting
230-
// from Medium. The original markup stucture that was pasted looked something like this:
231-
//
232-
// <section>
233-
// <div>
234-
// <div>
235-
// <h4>title</h4>
236-
// <ul><li>one - one</li></ul>
237-
// <figure><img /></figure>
238-
// <ul><li>two - one</li></ul>
239-
// </div>
240-
// </div>
241-
// </section>
242-
// <section>
243-
// <div><hr /></div>
244-
// <div><div><br /></div></div>
245-
// </section>
246-
//
247-
// NOTE: because DOMParser passes each top-level element to SectionParser rather
248-
// than passing the leaf-most section with content, the SectionParser needs to
249-
// deal with nested wrapper elements (section->div->div->[h4,ul,figure,ul])
250-
//
251-
// the error being thrown was
252-
// ---
253-
// Uncaught TypeError: Cannot read property 'append' of undefined
254-
// at SectionParser._createMarker
255-
// ---
256-
// the line in question was `state.section.markers.append(marker);`
257228
test('#parse handles list following node handled by parserPlugin', (assert) => {
258229
let container = buildDOM(`
259230
<div><img src="https://placehold.it/100x100"><ul><li>LI One</li></ul></div>
@@ -281,6 +252,19 @@ test('#parse handles list following node handled by parserPlugin', (assert) => {
281252

282253
let listSection = sections[1];
283254
assert.equal(listSection.type, 'list-section');
255+
assert.equal(listSection.items.length, 1, '1 list item');
256+
});
257+
258+
test('#parse avoids empty paragraph around wrapped list', (assert) => {
259+
let container = buildDOM(`
260+
<div><ul><li>One</li></ul></div>
261+
`);
262+
263+
let element = container.firstChild;
264+
parser = new SectionParser(builder);
265+
let sections = parser.parse(element);
266+
267+
assert.equal(sections.length, 1, 'single list section');
284268
});
285269

286270
test('#parse skips STYLE nodes', (assert) => {

0 commit comments

Comments
 (0)