node.jsjsdomobservable-plot

How to use Observable Plot in Nodejs?


I read that using jsdom is necessary for Observable Plot (derived module from D3js) to work in Nodejs.

However, there are very few examples about this and I cannot get to properly adapt the ones I found.

Here is the code I was trying to adapt:

import * as Plot from "@observablehq/plot";
import jsdom from "jsdom";

const { JSDOM } = jsdom;

const sales = [
  {units: 10, fruit: "fig"},
  {units: 20, fruit: "date"},
  {units: 40, fruit: "plum"},
  {units: 30, fruit: "plum"}
];

Plot.dot(sales, {x: "units", y: "fruit"}).plot();

I tried different things, like adding:

import {select} from "d3-selection";

Plot.select(JSDOM.window.document.body).dot(sales, {x: "units", y: "fruit"}).plot();

trying to reproduce what is done for d3 here.

I also saw this which might contain the answer, but this is not understandable for a javascript beginner like me.

How should I adapt my code ?


Solution

  • I was finally able to obtain what I want like this:

    import http from 'http';
    import * as Plot from "@observablehq/plot";
    import {JSDOM} from "jsdom";
    
    const jsdom = new JSDOM(`
    <!DOCTYPE html>
    <head><meta charset="UTF-8"></head>
    <body><div class='container'><figure id='graphic'>
    </figure></div></body>`);
    
    const sales = [
      {units: 10, fruit: "fig"},
      {units: 20, fruit: "date"},
      {units: 40, fruit: "plum"},
      {units: 30, fruit: "plum"}
    ];
    
    jsdom.window.document.getElementById('graphic')
                         .appendChild(Plot.dot(sales, {x: "units", y: "fruit"})
                                          .plot({document: jsdom.window.document})
                                     );
    
    http.createServer(function (req, res) {
      let html = jsdom.serialize();
      res.end(html);
    }).listen(8080);
    

    The jsdom object needed to be created less randomly and my way of using Plot.dot with jsdom was not correct. I also had to use the http module to render the graph in a browser, and access it at localhost:8080/.