Skip to content

Commit 2037d83

Browse files
5saviahvfb55
andauthored
feat(manipulation): Add unwrap function (#1651)
Co-authored-by: 5saviahv <[email protected]> Co-authored-by: Felix Böhm <[email protected]>
1 parent bb6cb38 commit 2037d83

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

lib/api/manipulation.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,47 @@ exports.wrapInner = _wrap(function (el, elInsertLocation, wrapperDom) {
364364
updateDOM(wrapperDom, el);
365365
});
366366

367+
/**
368+
* The .unwrap() function, removes the parents of the set of matched elements
369+
* from the DOM, leaving the matched elements in their place.
370+
*
371+
* @example <caption>without selector</caption>
372+
* const $ = cheerio.load(
373+
* '<div id=test>\n <div><p>Hello</p></div>\n <div><p>World</p></div>\n</div>'
374+
* );
375+
* $('#test p').unwrap();
376+
*
377+
* //=> <div id=test>
378+
* // <p>Hello</p>
379+
* // <p>World</p>
380+
* // </div>
381+
*
382+
* @example <caption>with selector</caption>
383+
* const $ = cheerio.load(
384+
* '<div id=test>\n <p>Hello</p>\n <b><p>World</p></b>\n</div>'
385+
* );
386+
* $('#test p').unwrap('b');
387+
*
388+
* //=> <div id=test>
389+
* // <p>Hello</p>
390+
* // <p>World</p>
391+
* // </div>
392+
*
393+
* @param {string} [selector] - A selector to check the parent element against. If
394+
* an element's parent does not match the selector, the element won't be unwrapped.
395+
* @see {@link https://api.jquery.com/unwrap/}
396+
* @returns {Cheerio} The instance itself, for chaining.
397+
*/
398+
exports.unwrap = function (selector) {
399+
var self = this;
400+
this.parent(selector)
401+
.not('body')
402+
.each(function (i, el) {
403+
self._make(el).replaceWith(el.children);
404+
});
405+
return this;
406+
};
407+
367408
/**
368409
* The .wrapAll() function can take any string or object that could be passed to
369410
* the $() function to specify a DOM structure. This structure may be nested

test/api/manipulation.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,89 @@ describe('$(...)', function () {
324324
});
325325
});
326326

327+
describe('.unwrap', function () {
328+
var $elem;
329+
var unwrapspans = [
330+
'<div id=unwrap style="display: none;">',
331+
'<div id=unwrap1><span class=unwrap>a</span><span class=unwrap>b</span></div>',
332+
'<div id=unwrap2><span class=unwrap>c</span><span class=unwrap>d</span></div>',
333+
'<div id=unwrap3><b><span class="unwrap unwrap3">e</span></b><b><span class="unwrap unwrap3">f</span></b></div>',
334+
'</div>',
335+
].join('');
336+
337+
beforeEach(function () {
338+
$elem = cheerio.load(unwrapspans);
339+
});
340+
341+
it('() : should be unwrap span elements', function () {
342+
var abcd = $elem('#unwrap1 > span, #unwrap2 > span').get();
343+
var abcdef = $elem('#unwrap span').get();
344+
345+
// make #unwrap1 and #unwrap2 go away
346+
expect(
347+
$elem('#unwrap1 span').add('#unwrap2 span:first-child').unwrap()
348+
).toHaveLength(3);
349+
350+
//.toEqual
351+
// all four spans should still exist
352+
expect($elem('#unwrap > span').get()).toEqual(abcd);
353+
354+
// make all b elements in #unwrap3 go away
355+
expect($elem('#unwrap3 span').unwrap().get()).toEqual(
356+
$elem('#unwrap3 > span').get()
357+
);
358+
359+
// make #unwrap3 go away
360+
expect($elem('#unwrap3 span').unwrap().get()).toEqual(
361+
$elem('#unwrap > span.unwrap3').get()
362+
);
363+
364+
// #unwrap only contains 6 child spans
365+
expect($elem('#unwrap').children().get()).toEqual(abcdef);
366+
367+
// make the 6 spans become children of body
368+
expect($elem('#unwrap > span').unwrap().get()).toEqual(
369+
$elem('body > span.unwrap').get()
370+
);
371+
372+
// can't unwrap children of body
373+
expect($elem('body > span.unwrap').unwrap().get()).toEqual(
374+
$elem('body > span.unwrap').get()
375+
);
376+
377+
// can't unwrap children of body
378+
expect($elem('body > span.unwrap').unwrap().get()).toEqual(abcdef);
379+
380+
// can't unwrap children of body
381+
expect($elem('body > span.unwrap').get()).toEqual(abcdef);
382+
});
383+
384+
it('(selector) : should only unwrap element parent what specified', function () {
385+
var abcd = $elem('#unwrap1 > span, #unwrap2 > span').get();
386+
// var abcdef = $elem('#unwrap span').get();
387+
388+
// Shouldn't unwrap, no match
389+
$elem('#unwrap1 span').unwrap('#unwrap2');
390+
expect($elem('#unwrap1')).toHaveLength(1);
391+
392+
// Shouldn't unwrap, no match
393+
$elem('#unwrap1 span').unwrap('span');
394+
expect($elem('#unwrap1')).toHaveLength(1);
395+
396+
// Unwraps
397+
$elem('#unwrap1 span').unwrap('#unwrap1');
398+
expect($elem('#unwrap1')).toHaveLength(0);
399+
400+
// Should not unwrap - unmatched unwrap
401+
$elem('#unwrap2 span').unwrap('quote');
402+
expect($elem('#unwrap > span')).toHaveLength(2);
403+
404+
// Check return values - matched unwrap
405+
$elem('#unwrap2 span').unwrap('#unwrap2');
406+
expect($elem('#unwrap > span').get()).toEqual(abcd);
407+
});
408+
});
409+
327410
describe('.wrapAll', function () {
328411
var doc;
329412
var $inner;

0 commit comments

Comments
 (0)