How do you share jsdom prototype extensions across modules in js/typescript?

38 views Asked by At

I've been migrating from constructing html elements in clientside runtime js for my blog post, to constructing them on build, using typescript and node, together with jsdom for html parsing/manipulation.

It's been working fine for the most part, except, extending DOM types, such as:

import { JSDOM } from "jsdom";

Document.prototype.createDiv = function (classes) {
    return this.createElem("div", classes);
}

which I can't for the life of me get to work across modules

I would've expected this to work, but I get ReferenceError: Document is not defined. So I figured it probably has something to do with jsdom not magically adding Document to the global scope, but after a lot of wrangling with this, I still can't get it to work the way I want.

The closest I've gotten it to work, is by creating an instance of jsdom and adding global declares for TS to be happy, like this:

import { JSDOM } from "jsdom";
const dummyDom = new JSDOM("");
const Document = dummyDom.window.Document;
declare global {
    module JSDOM{
        interface Document {
            createDiv(classes: string): HTMLElement;
            createElem(tagName: string, classes?: string): HTMLElement;
        }
    }
}
Document.prototype.createDiv = ...

And this makes it work, but only on this instance of JSDOM in this specific module, which isn't super helpful because I need to create new instances of every time I parse a new piece of HTML. Outside of this module, I instead get runtime type errors

TypeError: document.createElem is not a function

I think at this point I'm okay shelfing the dream of using the same implementation both for the runtime browser DOM as well as the build step jsdom, and instead just write duplicate code for either case.

The only solution I can think of right now is to write my own wrapper for JSDOM, that adds these prototypes every time I instantiate a new JSDOM object, but that feels pretty janky, especially if I start getting up there in number of extensions.

Is there a way to restore my sanity here? c:

0

There are 0 answers