Home > Mobile >  Adapting code that does dom manipulation to NodeJS
Adapting code that does dom manipulation to NodeJS

Time:11-24

An npm package I want to use contains code like this excerpt

    function callback(div, tune, tuneNumber, abcString) {
        var removeDiv = false;
        if (div === "*") {
            removeDiv = true;
            div = document.createElement("div");
            div.setAttribute("style", "visibility: hidden;");
            document.body.appendChild(div);
        }
        if (params.afterParsing)
            params.afterParsing(tune, tuneNumber, abcString);
        if (!removeDiv && params.wrap && params.staffwidth) {
            tune = doLineWrapping(div, tune, tuneNumber, abcString, params);
            return tune;
        }
        renderOne(div, tune, params, tuneNumber, 0);
        if (removeDiv)
            div.parentNode.removeChild(div);
        return null;
    }

As you can see it's riddled with DOM manipulation. This is super annoying considering that what it does is transform a string to another string (ABC music format to SVG).

I'm actually trying to use it in a vscode extension, which fundamentally makes this a Node app. I've read Emulate browser in node js and jsdom looks quite promising. What concerns me is code like this

document.body.appendChild(div);

because it assumes the existence of "ambient" objects like document.

  • Are libraries like jsdom able to address that kind of problem?
  • Is this the "pollution of the global namespace" that I'm endlessly warned about?
  • Can it be done (fake the DOM so this sort of code can run without a massive rewrite) and is a library like jsdom the right way to go about it for less demanding cases?

I'm aware that jsdom isn't a comprehensive browser mock so mileage may vary.

CodePudding user response:

Are libraries like jsdom able to address that kind of problem?

Yes, JSDom might be the one most suited for this situation.

Is this the "pollution of the global namespace" that I'm endlessly warned about?

There's no need for global pollution. All you really need is an identifier named document in scope at that time. It doesn't need to refer to a document on the global object. To do so in JSDom, all you need is:

const dom = new JSDOM(`<!DOCTYPE html>`);
const { document } = dom.window;
// you may also need
// const { window } = dom;

// paste the rest of your code here

It's not a full-fledged browser, but it's still pretty intricate and may well suit your needs. Go for it.

  • Related