
Research
GemStuffer Campaign Abuses RubyGems as Exfiltration Channel Targeting UK Local Government
GemStuffer abuses RubyGems as an exfiltration channel, packaging scraped UK council portal data into junk gems published from new accounts.
d3-textwrap
Advanced tools
wrap long lines of text using foreignObject tags or tspans as appropriate, depending on browser support
wrap long lines of text in SVG images
Astonishingly, SVG does not natively provide a way to wrap long lines of text. However, it does provide two mechanisms by which text wrapping can be very tediously implemented.
the long text can be split into substrings which are inserted into tspan elements, each of which is then positioned individually
the text can be added to a foreignObject which uses HTML instead of SVG to wrap long lines
The first approach can be buggy in Safari, and the second does not work at all in Internet Explorer 10 or below. This plugin implements both solutions, and can switch between them depending on browser support.
The d3.textwrap method is a factory which returns functions which can then have their wrapping behavior configured, and are then run on a set of text nodes using selection.call.
// create a text wrapping function
var wrap = d3.textwrap().bounds({height: 480, width: 960});
// wrap all text
d3.selectAll('text').call(wrap);
Install with npm or yarn, or download the latest release.
npm install d3-textwrap
You can import with ESM import syntax and then attach it to your d3 object:
import { textwrap } from 'd3-textwrap';
d3.textwrap = textwrap;
Or do the same with CJS require():
var textwrap = require('d3-textwrap').textwrap;
d3.textwrap = textwrap;
You can also load directly in the browser without a build tool or package manager. Add the plugin script to your HTML page after you've loaded d3.js and the textwrap() function will be automatically added to the d3 object:
<html>
<head>
<script type="text/javascript" src="https://d3js.org/d3.v5.min.js"></script>
<script type="text/javascript" src="/path/to/textwrap.js"></script>
</head>
# d3.textwrap
Creates a function that can then be configured and used to wrap text. This allows for varying configurations within the same project.
var wrap = d3.textwrap();
# textwrap.bounds(bounds)
Gets or sets the boundaries within which text will be wrapped. Takes one argument, which can be a DOM node, an object with "height" and "width" properties, or a function which returns an object with "height" and "width" properties. To wrap to a 480Ă—960 pixel rectangle:
var wrap;
// create a text wrapping function
wrap = d3.textwrap()
// wrap to 480 x 960 pixels
.bounds({height: 480, width: 960});
# textwrap.padding(padding)
Gets or sets optional additional padding which will be calculated on top of the bounds before the text wrapping is performed. Takes one argument, which can be a number or a function which returns a number. Note that this does not support CSS units. To pad by 10 pixels, thus bringing the effective dimensions to 460Ă—940:
var wrap;
// create a text wrapping function
wrap = d3.textwrap()
// wrap to 480 x 960 pixels
.bounds({height: 480, width: 960})
// pad by an additional 10 pixels
.padding(10);
# textwrap.method(method)
Gets or sets the name of the text wrapping method to be used, which can be either "foreignobject" or "tspans". If this is not specified, the default behavior is to use foreignobject wrapping for most browsers, but fall back to using tspan elements when that is not an available option. With that said, in some scenarios it may also make sense to always use the tspan method in pursuit of consistent behavior.
var wrap;
// create a text wrapping function
wrap = d3.textwrap()
// wrap to 480 x 960 pixels
.bounds({height: 480, width: 960})
// wrap with tspans in all browsers
.method('tspans');
After configuring a text wrapping function, run it using selection.call():
var wrap,
text;
// create a text wrapping function
wrap = d3.textwrap()
// wrap to 480 x 960 pixels
.bounds({height: 480, width: 960});
// select all text nodes
text = d3.selectAll('text');
// run the text wrapping function on all text nodes
text.call(wrap);
Gregor Aisch's handy d3-jetpack toolkit also provides a text wrapping routine which works by counting the number of characters on each line instead of measuring the amount of horizontal space they occupy.
FAQs
wrap long lines of text using foreignObject tags or tspans as appropriate, depending on browser support
The npm package d3-textwrap receives a total of 1,492 weekly downloads. As such, d3-textwrap popularity was classified as popular.
We found that d3-textwrap demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
GemStuffer abuses RubyGems as an exfiltration channel, packaging scraped UK council portal data into junk gems published from new accounts.

Company News
Socket was named to the Rising in Cyber 2026 list, recognizing 30 private cybersecurity startups selected by CISOs and security executives.

Research
Socket detected 84 compromised TanStack npm package artifacts modified with suspected CI credential-stealing malware.