Skip to content

πŸ“Š Fully use D3.js (Data Driven Documents) in environments without DOM. Perfect for serverless e.g. Vercel Functions

License

Notifications You must be signed in to change notification settings

neg4n/d3-no-dom

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

30 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

d3-no-dom

Fully use d3.js in environments without DOM, such as Cloudflare Workers or Vercel Functions

Features

  • Simple API with maximum extensibility.
  • Support for asynchronous operations and API calls in render function
  • Utilities like sanitizing the HTML or outputting the base64 from generated svg
  • Tests covering most of the functionality ensuring robustness

Installation

npm i d3-no-dom d3 
# or
yarn add d3-no-dom d3 
# or
pnpm add d3-no-dom d3 

The d3-no-dom library does not provide any underlying DOM implementation, giving users the flexibility to choose their preferred DOM library. Some options are:

npm i linkedom 
# or
yarn add linkedom 
# or
pnpm add linkedom 
  • jsdom: A more comprehensive and heavier DOM implementation, suitable for traditional backend environments like monolithic applications hosted on dedicated servers.
npm i jsdom 
# or
yarn add jsdom 
# or
pnpm add jsdom 

Warning

jsdom may not work on the Cloudflare Workers without specifying nodejs_compat flag due to use of the Node native modules

How to use

  1. At first, you must supply your own d3 instance and dom provider to the d3-no-dom's prepreSvgServerSideRenderer
  • using linkedom (recommended)

    import * as d3 from "d3"
    import { parseHTML } from "linkedom"
    
    // ...
    
    class Linkedom {
      window: { document: Document };
      constructor(html: string) {
        const { document, window } = parseHTML(html);
        this.window = { document };
        Object.assign(this.window, window);
      }
    }
    
    const { render } = prepareSvgServerSideRenderer({
      domProvider: Linkedom,
      d3Instance: d3
    });
  • using jsdom

    import * as d3 from "d3"
    import { JSDOM } from "jsdom"
    
    // ...
    
    const { render } = prepareSvgServerSideRenderer({
      domProvider: JSDOM,
      d3Instance: d3
    });
  1. Next, use the render function. It provides everything you need in order to fully use d3.js on the server side (the underlying mechanism is integration with Virtual DOM)
//               you can make e.g. API calls here   
//           it can also be synchronous if not needed!
//              ╭─────────────
//              β”‚            β”‚    
//              ↓            ↓ 
const result = await render(async ({ d3Selection, svgNode, currentDom }) => {
//      ↑                                  ↑        ↑          ↑            
//      β”‚                d3 selected       β”‚        β”‚          β”‚
//      β”‚                object to work on β•―        β”‚          β•° whole DOM  
//      β”‚                                      underlying
//      β•° rendered svg's                 svg DOM node to work on
//   source, as HTML or base64   
})
  1. (Optionally) adjust your configuration or the render function's options directly in order to e.g. disable sanitizing the HTML or control the return value (whether it should be HTML or base64 - where second is specifically useful with usage with satori)

License & contributing

The MIT License. All contributions are welcome!