npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@neo-ma/pptxgenjs-std

v0.4.0

Published

Layout and diagram helpers for @neo-ma/pptxgenjs

Readme

@neo-ma/pptxgenjs-std

Helpers that compose the public @neo-ma/pptxgenjs API. Plain functions, no runtime dependency on the core - every helper takes the object it acts on and calls the same addX methods you would.

They live outside the core on purpose: the core is an OOXML emitter bound by upstream API compatibility, while these are opinions about layout and diagram shapes that should be free to change.

Install

npm install @neo-ma/pptxgenjs-std

Beta. This package is 0.x and its API may change between minor versions. It is versioned independently of the core - the two version numbers are unrelated.

Requires @neo-ma/pptxgenjs 4.2.0 or later - waterfall relies on per-series 'transparent' colours (4.1.0) and per-point data labels (4.2.0), both silently ignored by older cores.

@neo-ma/pptxgenjs is a peer dependency, not a regular one: these helpers act on the slide objects your own presentation created, so a second copy of the core at another version would be exactly wrong. It is used for types only - nothing here imports it at runtime. The package ships dist/index.mjs and dist/index.cjs, so plain Node resolves both without a bundler. It versions independently from the core; its release tags are std-vX.Y.Z.

grid - placement without arithmetic

addText/addShape/addChart take absolute inches, which is where overlapping and off-slide content comes from. grid turns that into cell coordinates and throws on anything out of range.

import { grid } from '@neo-ma/pptxgenjs-std'

const at = grid() // 12 x 6 cells over a 10 x 5.625in slide, 0.5in margin, 0.2in gutter
slide.addText('Revenue', { ...at(0, 0, 12, 1), fontSize: 32 })
slide.addChart('bar', data, at(0, 1, 6, 5))
slide.addTable(rows, at(6, 1, 6, 5))

at(12, 0) // throws: col 12 span 1 exceeds 12 columns

gridFor(pres, opts) reads the size from pres.presLayout, so it follows layout and defineLayout.

row / column - divide an area

grid needs integer spans over a fixed cell count; these take any area and split it, so nested and uneven layouts do not need a second grid. A number means equal slots, an array means weights.

import { grid, row, column } from '@neo-ma/pptxgenjs-std'

const [header, body] = column(grid()(0, 0, 12, 6), [1, 4])
const [left, right] = row(body, [1, 2])

Output is the same { x, y, w, h } shape as the input, so slots nest.

cm / pt - inches, from the unit you designed in

Every addX option is in inches. A layout specified in centimetres - most of them outside the US - otherwise gets a / 2.54 at every call site until one of them is wrong.

import { cm, grid, pt } from '@neo-ma/pptxgenjs-std'

slide.addText('Titel', { x: cm(2.5), y: cm(1.8), w: cm(20), h: cm(2) })
const at = grid({ w: cm(33.87), h: cm(19.05), margin: cm(1.27) })
slide.addShape('line', { x: 1, y: pt(18), w: 4, h: 0 })

measureText / fitText - text size, computed

Nothing in a .pptx records where text wraps. measureText works it out, using a browser canvas when there is one, bundled advance widths otherwise (Calibri, via the metric-compatible OFL font Carlito), and a flat estimate as a last resort - source on the result says which. fitText binary searches it for the largest whole point size that fits a box.

import { measureText, fitText } from '@neo-ma/pptxgenjs-std'

const { h } = measureText(paragraph, { w: 4, fontSize: 14 })
const { fontSize } = fitText({ w: 4, h: 2 }, headline)

checkOverflow is the other direction - the size is fixed, the question is whether it fits, which is what a QA pass over a finished deck asks. It reports overflowBy in inches, so a finding can say how far the text spills rather than only that it does.

import { checkOverflow } from '@neo-ma/pptxgenjs-std'

const { overflows, overflowBy } = checkOverflow(box, body, { fontSize: 11 })

registerFontMetrics(face, { widths }) adds a font; scripts/extract-font-metrics.mjs generates the table from a .ttf.

paginateTable / tableFromHtml - tables across slides

The core's autoPage guesses where rows break from a per-character constant, which is why it ships autoPageCharWeight to tune by hand. These measure each cell instead.

import { paginateTable } from '@neo-ma/pptxgenjs-std'

paginateTable(pres, rows, { x: 0.5, y: 0.5, w: 9, fontSize: 11, repeatHeaderRows: 1 })

They take the presentation, not a slide, because they create the slides. tableFromHtml is the same thing over a table-shaped object - a live <table> or anything with rows/cells.

waterfall - bridge chart

PowerPoint has no waterfall type reachable through ECMA-376 c:barChart. This builds the standard construction: a stacked bar chart with a transparent riser carrying each bar to its starting value, plus separate increase/decrease series so each side keeps its own color and signed data label.

import { waterfall } from '@neo-ma/pptxgenjs-std'

waterfall(slide, {
	labels: ['Opening', 'New sales', 'Churn', 'Upsell'],
	values: [1200, 340, -180, 95],
	total: 'Closing',
}, { x: 0.5, y: 0.5, w: 9, h: 4.5, showValue: true })

values are signed deltas. Everything after props is passed through to addChart, so titles, axes and label formatting work as usual - only barDir, barGrouping and the series colors are fixed.