Matthew Groves
Matthew Groves

Reputation: 26096

Using JavaScript DOM in VSCode extension

I am trying to create a Visual Studio Code extension that will apply YoastSEO analysis to documents that I'm writing in Visual Studio Code (e.g. txt files, markdown files, asciidoc files, etc).

I have created a basic shell of an extension, and I have used npm to add YoastSEO: npm install https://github.com/Yoast/YoastSEO.js#develop

I've created a YoastProvider class like so:

const timerPeriod = 1000;  // Time between preview updates

export default class YoastProvider implements TextDocumentContentProvider {
  // ...
}

Now within this class, there is a preview method that I want to use to 1) get the contents of the document, 2) process with Yoast, 3) output the result to a preview pane.

The thing is, the Yoast API wants to work directly with the DOM. Here's an example from their github:

var snippetPreview = new SnippetPreview({
    targetElement: document.getElementById( "snippet" )
});

var app = new App({
    snippetPreview: snippetPreview,
    targets: {
        output: "output"
    },
    callbacks: {
        getData: function() {
            return {
                keyword: focusKeywordField.value,
                text: contentField.value
            };
        }
    }
});

app.refresh();

I can "fake" out an element with nodom and I can pass strings directly to keyword and text, but it doesn't matter because Yoast seems to use the DOM during its processing. So I get an error that document is undefined from within Yoast's app.js.

Is there any way to use YoastSEO in this manner? Is there some other approach that I'm missing? Seems like I might be making it harder than it should be.

Upvotes: 0

Views: 1786

Answers (1)

David Driscoll
David Driscoll

Reputation: 1419

It may be possible to wrap Yoast in a new context that contains something like jsdom, so that when it loads it appears as if the dom is there.

I've dome similar things to run angular unit tests inside the node environment using jsdom myself.

const yoast = (function(){
    global.document = jsdom(); // Use any virtual dom that you want really
    const yoast = require('yoast');
    delete global.document;
    return yoast;
})();

Sadly it's not as easy as simply importing the module, but it should get the job done.

Upvotes: 2

Related Questions