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

@domternal/extension-image

v1.8.0

Published

Image node extension for Domternal editor

Readme

@domternal/extension-image

Version MIT License

Images for the Domternal editor, with resizing, alignment, text wrapping, alt text and file paste/drop support. Store files through your own upload handler or embed them as data URLs. Images are block nodes by default; inline images are optional.

Documentation · Examples

Install

The package declares Node.js 22 or later for tooling.

pnpm add @domternal/core @domternal/pm @domternal/extension-image @domternal/theme

Core and pm are peers with the range >=1.8.0 <2.0.0. Use version 1.8.0 for all installed Domternal Free packages. The optional theme provides the resize handles, placement styles and upload indicator; supply equivalent CSS if you omit it. Exported HTML includes placement styles independently of the theme.

Quick start

<div id="editor" class="dm-editor"></div>
import { Editor, StarterKit } from '@domternal/core';
import { Image } from '@domternal/extension-image';
import '@domternal/theme';

const editor = new Editor({
  element: document.getElementById('editor')!,
  extensions: [StarterKit, Image],
  content: '<p>Paste an image or add one by URL.</p>',
});

Add an image using a URL your application serves:

editor.chain().focus().setImage({
  src: '/uploads/photo.jpg',
  alt: 'A mountain reflected in a lake',
}).run();

Call editor.destroy() when removing the editor. The extension contributes image controls to Domternal's toolbar and bubble menu when those UI components are mounted; a bare Core editor does not create those components.

Upload files to your application

Without an upload handler, accepted files are embedded in the document as data URLs. To store files elsewhere, replace Image in the extension array with a configured instance. This example expects your own /api/upload endpoint to return JSON containing a url string:

Image.configure({
  allowBase64: false,
  allowedMimeTypes: ['image/jpeg', 'image/png', 'image/webp'],
  maxFileSize: 5 * 1024 * 1024,
  maxFiles: 5,
  uploadHandler: async (file) => {
    const form = new FormData();
    form.append('file', file);
    const response = await fetch('/api/upload', { method: 'POST', body: form });
    if (!response.ok) throw new Error('Image upload failed');

    const result = await response.json() as { url?: unknown };
    if (typeof result.url !== 'string' || !result.url) {
      throw new Error('The upload endpoint did not return an image URL');
    }
    return result.url;
  },
  onUploadError: (error) => {
    console.error(error.message);
  },
});

The same MIME, size and count rules apply to pasted, dropped and file-picker images. Validate uploads on your server too. Files keep their insertion order while asynchronous uploads finish. The theme renders the .domternal-image-uploading placeholder as a localized loading status with a light/dark indicator. It respects reduced motion and is hidden when printing. It is view-only, has no keyboard stop and never enters saved content or Undo history. A failed upload or deletion of its insertion point removes the loading indicator. See file insertion and undo for selection replacement, cancellation and collaborative edits.

Common options

| Option | Default | Purpose | | --- | --- | --- | | inline | false | Place images inside text instead of as blocks. | | enableTransforms | false | Opt into the image geometry schema attribute and crop, rotate and mirror commands. | | placement | null | Let the preset choose float or align controls; set 'float' or 'align' explicitly to override. | | allowBase64 | true | Accept image data URLs and embed files when no upload handler is supplied. | | uploadHandler | null | Store a file and return its URL. | | maxFileSize | 0 | Maximum bytes per file; 0 leaves size unlimited. | | maxFiles | 10 | Maximum accepted files per operation; 0 removes the count limit. | | allowedMimeTypes | JPEG, PNG, GIF, WebP, SVG, AVIF | MIME types accepted for files. |

With allowBase64: false and no uploadHandler, files cannot be inserted. Remote image URLs can still be used. The full option reference also covers HTML attributes and upload callbacks.

Commands and alt text

| Command | Purpose | | --- | --- | | setImage({ src, alt, ... }) | Insert an image with its attributes. | | setImageFloat('left') | Wrap text around the selected image. | | setImageAlign('center') | Align the selected image without text wrapping. | | setImageTransform({ crop, rotation, flipX, flipY }) | With enableTransforms: true, replace the selected image's non-destructive geometry; null resets it. | | deleteImage() | Remove the selected image. |

Float and align each accept 'none', 'left', 'center' and 'right'; setting one clears the other. Commands operate on the current selection.

Use a descriptive alt for meaningful images. alt: '' marks an image as decorative and renders alt=""; null means no description has been supplied and omits the attribute. See alt text editing.

Crop, rotate and mirror images

Free 1.6.0 adds non-destructive image geometry. Enable it explicitly in the editor's extension array:

Image.configure({ enableTransforms: true });

The default Image schema and ordinary image JSON stay unchanged. Enabling this option adds the imageTransform attribute, with a default of null. Update any strict application schema to allow that field and enable the option in every collaborating editor before storing transformed images. Editors without the option cannot preserve geometry from an enabled editor.

The imageTransform attribute keeps source bytes unchanged. Cropping uses fractions of the original image, followed by horizontal/vertical mirroring and clockwise rotation. The editor and saved HTML use a viewport with the rotated bounding box; resizing changes that box's width while preserving its aspect ratio.

editor.commands.setImageTransform({
  naturalWidth: 1600,
  naturalHeight: 900,
  crop: { left: 0.1, right: 0.1 },
  rotation: 90,
  flipX: true,
});

The command requires an image node selection. Omit naturalWidth and naturalHeight only when that image is loaded, or when its current transform already records them. setImage({ src, imageTransform: { ... } }) always needs explicit intrinsic dimensions. A command replaces the complete transform and is undoable; loading, rendering and exporting never author geometry in the document. Without enableTransforms: true, setImageTransform and setImage with an explicit transform or null return false without changing the document. No crop/rotation controls are added to the default menu.

Each crop edge must be between zero and one, with at least 1/65,536 of the image remaining in both directions. Intrinsic dimensions must be finite and between 1 and 1,000,000; rotation must be finite within plus or minus 1,000,000 degrees. Whole turns are normalized away. Invalid commands return false, malformed stored geometry renders as an ordinary image, and null or identity transforms keep ordinary image markup unchanged. The ImageTransform and SetImageTransformOptions types are exported for application controls.

Clipboard and source policy

A screenshot or image-only clipboard inserts image files. When copied content has text of its own, the HTML/text takes priority so Word's picture of a copied selection does not replace the actual content. Office HTML normalization is a separate opt-in PasteCleanup feature; Image alone does not apply its raster or structural limits.

Built-in parsing, commands and rendering apply Core's URL policy. A refused stored source remains in JSON but is not loaded by the node view. URL checks do not inspect remote response bytes. See image security and the URL policy reference.

More documentation

  • Image guide: inline mode, popovers, resizing, file handling and node views.
  • Clipboard destinations: cooperating with a custom image node.
  • Localization: imageMessages and optional @domternal/extension-image/locales/de catalogs. Authored alt text is never translated.

License

MIT.