7

I have webfontloader working nicely within a browser context. Now I'm trying to see whether I can get it working in a node.js + jsdom context, particularly since webfontloader is available as an npm module.

I have got node + jsdom working to provide sensible output, so I know that part is working. But when I try to integrate webfontloader, to enable web fonts, I come unstuck.

Basically I am using webfontloader module as documented in the README, which is:

var WebFont = require('webfontloader');

WebFont.load({
  google: {
    families: ['Droid Sans', 'Droid Serif']
  }
});

But try as I may, I get the following error:

ReferenceError: window is not defined

I can get a window object from jsdom:

            // Get the document and window
            var doc = jsdom.jsdom('<!doctype html><html><body><div id="container"></div></body></html>'),
                win = doc.defaultView;

But how do I pass win in to webfontloader for use as window in that context?

Maybe I'm showing my naivety, and asking the impossible.

drmrbrewer
  • 11,491
  • 21
  • 85
  • 181

1 Answers1

1

Unless you have a good reason not to do so, i'd rather recommend you loading webfontloader into jsdom with jsdom.env or jsdom.jsdom, either using the version hosted on Google Hosted Libraries or hosting it yourself. Using jsdom.env it would look like this:

var jsdom = require("jsdom");

jsdom.env( 
    '<!doctype html><html><body></body></html>', 
    ['https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js'], 
    function(err, win) {

        var WebFont = win.WebFont;

        WebFont.load({
            google: {
                families: ['Droid Sans', 'Droid Serif']
            }
        });
    }
);

If you really need to require webfontloader from a nodejs context, as far as i can tell webfontloader can't be passed a window as a parameter, but you can circumvent this easily by adding a couple of lines to the library.

  1. Run npm install webfontloader
  2. Open "node_modules/webfontloader/webfontloader.js"
  3. Enclose the content of "webfontloader.js" in a module.exports function that takes a window object as a parameter.

The file could look similar to this (not pasting the whole webfontloader library source):

module.exports = function(window){

    var exportsBackup = module.exports;

    /* Web Font Loader v1.6.16 - (c) Adobe Systems, Google. License: Apache 2.0 */
    (function(){function aa(a,b,c){r ...

    var loaderObject = module.exports;
    module.exports   = exportsBackup;

    return loaderObject;
};

I do temporarily store module.exports in a variable to ensure we can require the module in this fashion multiple times, since the webfontloader library will replace the module.exports object.

You can require the library like this without any errors:

var jsdom = require("jsdom");

jsdom.env( "https://nodejs.org/", [], function(err, win) {

    var WebFont = require('webfontloader')(win);

    WebFont.load({
        google: {
            families: ['Droid Sans', 'Droid Serif']
        }
    });

});
cviejo
  • 4,388
  • 19
  • 30
  • Using the cunning suggestion of editing `webfontloader.js` to enable passing of `window` as a parameter, I can now get as far as actually invoking the `WebFont.load()` function without the Reference error. But now I'm getting exactly the same issue as described here: http://stackoverflow.com/q/34163339/4070848 -- in other words, the attempted loading of webfont always reaches the `inactive` branch, and never successfully loads. Are you able to get a webfont loaded successfully with `jsdom`? And I tried passing a custom `userAgent` to `jsdom` to try and trick webfontloader, to no avail. – drmrbrewer Dec 31 '15 at 16:23
  • Ok, i'll take a look into into. But first, happy new year! – cviejo Dec 31 '15 at 16:43
  • Happy new year (nearly!) as well... some are in the new year, others not quite! – drmrbrewer Dec 31 '15 at 16:47
  • There's a couple of open issues on github about this, seems like there's no support for font-face in jsdom, so not sure you can get around this easily, even if you change the UA. – cviejo Jan 02 '16 at 09:30
  • OK so it looks like my plan is foiled (can't get webfonts to work either with phantomjs or with jsdom) :-( Thanks for looking into this. Do you have the github links handy? If it's a fundamental issue with jsdom, I'll still mark your answer as correct (and award the bounty!) because it seems to be spot on (as far as actually getting webfontloader to play with jsdom, even if jsdom doesn't want to play back!) – drmrbrewer Jan 02 '16 at 10:06
  • Indirectly related: [this issue](https://github.com/tmpvar/jsdom/issues/744) and [this one from another project](https://github.com/peerlibrary/meteor-pdf.js/issues/7). But since you mention phantomjs, webfontsloader works just fine with it (just tried it). – cviejo Jan 02 '16 at 17:02
  • Thanks @cviejo. Re phantomjs... ooh is there any trick to getting it to work? As set out in my other post (http://stackoverflow.com/questions/34163339/phantomjs-web-fonts-font-loader) I just keep reaching `inactive`. Do you have a simple code example for phantomjs which you could share? Thanks :) – drmrbrewer Jan 02 '16 at 20:52
  • Sure, will post it on the other question as answer, it fits better there – cviejo Jan 03 '16 at 18:02