Working in JSDOM or Node.js natively


#1

Just curious if anyone has tried getting codemirror running inside of a virtual dom environment like JSDOM. I’m generating server side html with React and then bootstrapping codemirror in the browser, but this leads to a rather long and unpleasant flash of unstyled text area. I’d like to be able to generate a full (static) DOM tree with codemirror so that things are at least styled before they are functional. The current attempt in JSDOM leads to: TypeError: Object [ BODY ] has no method ‘createTextRange’, which I’m looking into.


#2

Alright, injecting this code is enough to get it to not error out:

        document.createRange = function() {
            return {
                setEnd: function(){},
                setStart: function(){},
                getBoundingClientRect: function(){
                    return {right: 0};
                }
            }
        };

It still doesn’t render correctly, but I’ll keep working on it. I see PhantomJS is how you’re running tests, but I think it will be too heavy for my use case. I may try that out as well.


#3

Hey man!, were you able to run it in the backend or not? I’m getting an error:

/Users/danielzamorano/workspace/basepath/node_modules/codemirror/lib/codemirror.js:25
var gecko = /gecko/\d/i.test(navigator.userAgent);

I’m also using JSDOM


#4

Nevermind I found the solution:

var expect = require(‘chai’).expect;
var jsdom = require(‘node-jsdom’);
var sinon = require(‘sinon’);

// virtual DOM environment for codemirror
global.navigator = ‘gecko’;
global.document = jsdom.jsdom();
global.window = global.document.defaultView;

var markdownEditor = require(’…/…/…/app/Authoring/Edit/markdown_editor.js’);


#5

I used boucher’s approach and that’s how initialization looks for me (I believe you shoud define createTextRange, not just createRange):

    import jsdom from 'jsdom'
    const doc = jsdom.jsdom('<!doctype html><html><body></body></html>')
    global.document = doc
    global.window = doc.defaultView
    global.document.body.createTextRange = function() {
        return {
            setEnd: function(){},
            setStart: function(){},
            getBoundingClientRect: function(){
                return {right: 0};
            },
            getClientRects: function(){
                return {
                    length: 0,
                    left: 0,
                    right: 0
                }
            }
        }
    }

#6

Still see this warning document.body.createTextRange is not a function