cheeriojs / cheerio

The fast, flexible, and elegant library for parsing and manipulating HTML and XML.
https://cheerio.js.org
MIT License
28.69k stars 1.64k forks source link

Chaining `replaceWith` method takes only the first one #3884

Closed MatteoGauthier closed 4 months ago

MatteoGauthier commented 4 months ago

Hello

When attempting to replace multiple elements in sequence using Cheerio, the second replacement operation seems to be ignored. The provided test case aims to replace occurrences of <li> tags and the text "Plum" string, but the second replacement with <li class="juice">Juice</li> does not take effect as expected.

Reproduction

In the manipulation.spec.ts file add this test case to the replaceWith describe

    it('(elem) : should replace 2 times', () => {
      const $plum = $('<li class="plum">Plum</li>');
      $('.orange').replaceWith($plum).replaceWith(
        '<li class="juice">Juice</li>'
      )

      expect($('.apple').next().hasClass('juice')).toBe(true);
      expect($('.apple').next().html()).toBe('Juice');
      expect($('.pear').prev().hasClass('juice')).toBe(true);
      expect($('.pear').prev().html()).toBe('Juice');
    });
prokoma commented 4 months ago

This is not a bug, replaceWith returns the original detached element, not the new one.

fb55 commented 4 months ago

Thank you @prokoma!

@MatteoGauthier Curious what your use-case is for chaining these — replacing and immediately replacing again seems counter-intuitive?

MatteoGauthier commented 4 months ago

Ok my bad, thanks @prokoma for your explanation, I've found a workaround