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

@imgly/idml-exporter

v0.1.0

Published

Export CE.SDK scenes as Adobe InDesign IDML files

Readme

@imgly/idml-exporter

Export CE.SDK scenes as Adobe InDesign IDML files.

Installation

npm install @imgly/[email protected] @cesdk/[email protected]

Quick Start

import CreativeEngine from '@cesdk/node'; // or @cesdk/engine in the browser
import { exportIdml } from '@imgly/idml-exporter';

const engine = await CreativeEngine.init({ license: 'YOUR_LICENSE' });
await engine.scene.loadFromArchiveURL('https://example.com/scene.zip');

const { idml, logger } = await exportIdml(engine);

// Write the .idml package to disk (Node.js)
import fs from 'fs/promises';
await fs.writeFile('./design.idml', idml);

// Everything IDML cannot represent is reported, never dropped silently.
for (const message of logger.getMessages()) {
  console.warn(`${message.type}: ${message.code} — ${message.message}`);
}

engine.dispose();

The generated file opens directly in Adobe InDesign (validated against Adobe's IDML schema and verified in InDesign 2026 — see docs/capability-verification.md).


API

exportIdml(engine)

For a self-contained hand-off, exportIdmlPackage(engine, { name }) returns a zip of <name>/<name>.idml plus a Document fonts/ folder with every font the text uses (fetched and converted to raw TTF/OTF) — Adobe's package convention, so InDesign activates them on open. IDML itself cannot embed fonts.

Distinct font subsets that share a family/style keep separate packaged faces. Their internal names and Story references receive matching aliases; exact prepared-font duplicates share one file. CFF glyph data remains unchanged and the renamed TTF/OTF files retain valid OpenType checksums. Standalone exportIdml emits FONT_NAMES_ALIASED when these aliases are required: use exportIdmlPackage, or place the collectDocumentFonts files in the adjacent Document fonts folder. Fonts installed under their original colliding names cannot resolve the new unique Story names.

Visible letters, numbers, punctuation or symbols missing from the declared font's Unicode cmap may use native fallback fonts that public text runs do not report. TEXT_FONT_FALLBACK_RASTERIZED preserves the complete native text paint as an embedded image. Covered text stays editable, including canonically covered compositions. Missing visible bases within combining or ZWJ sequences are detected; marks and default ignorable characters alone do not trigger a fallback. Coverage does not require Intl.Segmenter. If rendering fails, TEXT_FONT_FALLBACK_RASTERIZATION_FAILED reports the possible glyph loss.

Blocks excluded from export, including descendants of excluded groups, pages or scene ancestors, are omitted before rendering or collecting fonts. Excluded pages retain their dimensions as empty page containers. Visibility remains a separate editable state for included objects.

Exports the engine's current scene — every page — as one IDML package.

const result = await exportIdml(engine);

Returns

interface IDMLExportResult {
  idml: Uint8Array; // The .idml package (a zip archive)
  logger: Logger; // Diagnostics collected while exporting
}

Log messages

logger.getMessages() returns LogMessage[]:

interface LogMessage {
  type: 'info' | 'warning' | 'error';
  code: WarningCode; // e.g. "BLEND_MODE_DROPPED", "EFFECTS_BAKED"
  message: string;
  meta?: Record<string, unknown>;
}

| Code | Type | Meaning | | --------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------- | | FILL_ALPHA_FOLDED | info | A fill's alpha became fill-target opacity, independently of the stroke | | GRADIENT_ALPHA_AS_FEATHER | info | Varying gradient stop alpha became an InDesign Gradient Feather | | DEGENERATE_GRADIENT_AS_SOLID | info | Coincident linear handles or a zero radial radius became editable terminal-stop solid paint | | EFFECTS_BAKED | info | A block's effects/blur were baked into an embedded image | | EFFECTS_BAKE_FAILED | warning | Rendering enabled effects/blur failed; the editable object omits those effects/blur | | BLEND_MODE_DROPPED | warning | A CE.SDK-only blend mode (LinearBurn, VividLight, …) has no IDML form | | VIDEO_FILL_DROPPED | warning | No poster frame could be rendered for a video fill | | UNSUPPORTED_BLOCK_TYPE | warning | A block type (e.g. audio) was skipped | | LINE_SHAPE_RASTERIZED | warning | Native line paint became an image instead of a rectangle approximation; the line is no longer editable | | LINE_SHAPE_RASTERIZATION_FAILED | warning | Rendering the line failed; its rectangle approximation may differ | | UNSUPPORTED_SHAPE_TYPE | warning | A shape with no IDML form was exported as a plain rectangle | | UNSUPPORTED_PATH_DATA | warning | A vector path with unsupported commands was exported as a plain rectangle | | CROP_FLIP_ROTATION_APPROX | warning | Legacy code, no longer emitted: crop rotation and frame reflection are preserved separately | | IMAGE_BYTES_UNAVAILABLE | warning | An image's bytes could not be read | | TEXT_WITHOUT_FONT | warning | A text block's font could not be resolved; leading exported as auto | | TEXT_CASE_NORMALIZED | info | Lowercase/titlecase became editable normal text; the original case-transform style is flattened | | TEXT_CASE_RASTERIZED | warning | Font-dependent case could not be reproduced as editable text; native appearance became an image | | TEXT_CASE_RASTERIZATION_FAILED | warning | Rendering font-dependent case failed; normalized editable text may have a different visible case | | TEXT_PARAGRAPH_SPACING_RASTERIZED | warning | Mixed-font paragraph gaps preserve their terminal visual line as an image; text is no longer editable | | TEXT_PARAGRAPH_SPACING_RASTERIZATION_FAILED | warning | Rendering mixed-font paragraph gaps failed; editable gaps use each paragraph's first font | | TEXT_LEADING_RASTERIZED | warning | Combined ascender/descender metrics cannot be represented by character leading; native line placement became an image | | TEXT_LEADING_RASTERIZATION_FAILED | warning | Rendering combined leading failed; individual character leading may change line placement | | TEXT_TABS_RASTERIZED | warning | Native tab placement became an embedded image; text is no longer editable | | TEXT_TABS_RASTERIZATION_FAILED | warning | Rendering native tabs failed; editable tab placement may differ | | TEXT_PAINT_RASTERIZED | warning | Independent glyph paints became an embedded image; the text is no longer editable | | TEXT_PAINT_RASTERIZATION_FAILED | warning | Rendering independent glyph paints failed; paint transparency may differ | | UNDERLINE_METRICS_UNAVAILABLE | warning | The underline's font metrics were unavailable; custom dimensions could not be written | | TEXT_SCRIPT_RASTERIZED | warning | Superscript/subscript became an embedded image; the text is no longer editable | | TEXT_SCRIPT_RASTERIZATION_FAILED | warning | Rendering script styling failed; its position could not be preserved | | SHADOW_RASTERIZED | warning | Different horizontal/vertical shadow blur radii became an embedded image; the object is no longer editable | | SHADOW_RASTERIZATION_FAILED | warning | Rendering a nonuniform shadow failed; vertical blur uses the horizontal radius | | SHADOW_CLIP_RASTERIZED | warning | Shape shadow clipping and complete object paint became an image; the graphic is no longer editable | | SHADOW_CLIP_RASTERIZATION_FAILED | warning | Rendering a clipped shape shadow failed; native editable shadow paint omits shape/stroke clipping | | SHADOW_SIZE_RASTERIZED | warning | Shadow blur outside IDML's 0..144 point range became an embedded image with complete object paint | | SHADOW_SIZE_RASTERIZATION_FAILED | warning | Rendering an unsupported shadow blur failed; the shadow was omitted rather than writing invalid IDML | | SHADOW_OFFSET_RASTERIZED | warning | Shadow offsets outside IDML's -1000..1000 point range became an embedded image with complete object paint | | SHADOW_OFFSET_RASTERIZATION_FAILED | warning | Rendering unsupported shadow offsets failed; the shadow was omitted rather than writing invalid IDML | | SHAPE_CORNERS_RASTERIZED | warning | Rounded polygon/star/vector-path appearance became an embedded image; the shape is no longer editable | | SHAPE_CORNERS_RASTERIZATION_FAILED | warning | Rendering rounded corners failed; the shape's corners remain sharp | | TEXT_PATH_RASTERIZED | warning | Curved text became an embedded image preserving path offset/underside placement; it is no longer editable | | TEXT_PATH_RASTERIZATION_FAILED | warning | Rendering curved text failed; editable text uses a straight baseline | | FILL_RULE_RASTERIZED | warning | Winding-sensitive NonZero path fill became an embedded image; the path is no longer editable | | FILL_RULE_RASTERIZATION_FAILED | warning | Rendering NonZero path fill failed; winding-sensitive areas may differ | | UNSUPPORTED_FILL_RASTERIZED | warning | Conical, stripe or other non-native fill paint became an embedded image | | UNSUPPORTED_FILL_RASTERIZATION_FAILED | warning | Rendering a non-native fill failed; the fill was explicitly omitted | | PAGE_APPEARANCE_RASTERIZED | warning | Page background effects/blur became an image; foreground objects remain separately editable | | PAGE_APPEARANCE_RASTERIZATION_FAILED | warning | Rendering page background effects/blur failed; those effects were omitted | | STROKE_RASTERIZED | warning | Graphic dash lengths, phase and endpoint caps became an image; the graphic is no longer editable | | STROKE_RASTERIZATION_FAILED | warning | Rendering the graphic contour failed; native stroke attributes approximate its pattern/caps | | PAGE_STROKE_RASTERIZED | warning | The page contour and background became an image; foreground objects remain separately editable | | PAGE_STROKE_RASTERIZATION_FAILED | warning | Rendering the page contour failed; native rectangle attributes approximate its paint | | PAGE_VIDEO_RASTERIZED | warning | The video page background became a still poster image; foreground objects remain separately editable | | PAGE_VIDEO_RASTERIZATION_FAILED | warning | Rendering the video page background failed; its poster could not be preserved | | TEXT_STROKE_RASTERIZED | warning | Glyph stroke dashes or inside alignment became an image; text is no longer editable | | TEXT_STROKE_RASTERIZATION_FAILED | warning | Rendering glyph stroke geometry failed; editable text uses a solid centered outline | | TEXT_DECORATION_RASTERIZED | warning | Overline and all text paint became an embedded image; the text is no longer editable | | TEXT_DECORATION_RASTERIZATION_FAILED | warning | Rendering overline failed; editable text omits the overline | | TEXT_RANGE_BACKGROUND_RASTERIZED | warning | Text range highlights and all text paint became an image; the text is no longer editable | | TEXT_RANGE_BACKGROUND_RASTERIZATION_FAILED | warning | Rendering range highlights failed; editable text omits those backgrounds | | TEXT_BACKGROUND_BLEND_RASTERIZED | warning | Text and its background became one embedded image so their blend mode is applied once; text is no longer editable | | TEXT_BACKGROUND_BLEND_RASTERIZATION_FAILED | warning | Rendering combined text/background paints failed; separately blended editable paints may differ in color | | TEXT_XML_RASTERIZED | warning | Text or required font names containing characters forbidden by XML 1.0 became an image preserving appearance | | TEXT_XML_RASTERIZATION_FAILED | warning | Rendering text forbidden by XML 1.0 failed; those characters were replaced in editable text | | XML_CHARACTERS_REPLACED | warning | A forbidden XML scalar in a name or other field became U+FFFD; diagnostic metadata identifies the field | | XML_ID_REPLACED | warning | A metadata object ID containing forbidden XML scalars was replaced with a new unique ID |


What is exported

Clipped shape shadows use a diagnosed image fallback to preserve exclusion of the complete shape and its outer/center stroke, including translucent or hollow objects. Unclipped shadows within IDML's limits remain native. Disabled and transparent shadows do not trigger a fallback; text's inactive shadow clip setting does not trigger one either.

Conical and stripe fills, page background effects and nonstandard glyph strokes are preserved through the renderer when IDML has no matching native paint. Background bakes exclude copied foreground objects, which remain separately editable. Solid glyph strokes retain centered/outside alignment and miter, round or bevel joins as native editable IDML character attributes. Graphic stroke patterns, custom dash arrays/phase and nondefault open-path endpoint caps use a diagnosed image fallback. Page contours are preserved even with their fill disabled, and video page backgrounds become still posters when the engine runtime can decode their video. If decoding is unavailable, PAGE_VIDEO_RASTERIZATION_FAILED warns that the poster could not be preserved; the exporter cannot recover a frame from an unsupported decoder. Text with a visible block background and a non-normal blend mode uses one combined image so glyphs do not blend again against their own background. Object opacity, glyph shadows and the containing group's appearance remain part of that same composition. Zero-length linear gradients and zero-radius radial gradients become their terminal-stop solid color; positive fill and feather lengths remain nonzero even below ordinary XML number-rounding precision. Paragraph spacing follows each paragraph's own font metrics. Mixed-font paragraphs with nonzero spacing use the renderer to retain the combined metrics of their terminal visual line, including wraps. Text decorations follow the original UTF-16 ranges across emoji and combining sequences. Fixed-size text frames with clipping enabled retain their dimensions, as do frames with actually clipped lines, so auto-sizing cannot reveal intentionally hidden content. Automatically sized frames without clipped lines retain their authored Auto width and/or height even when clipping is enabled. Unavailable clipping observations keep the existing fixed-frame behavior. The paired importer restores fixed-frame clipping. XML 1.0 forbids some characters accepted by the engine: visible text and required font names use the same diagnosed image fallback; names and other fields use U+FFFD with field diagnostics, and invalid metadata IDs receive new unique IDs. Object/resource IDs and spread filenames are allocated uniquely even when imported metadata IDs collide with generated or built-in IDs, or different page IDs produce the same sanitized filename.

  • Pages → one IDML spread per page (size, name, bleed), preserving horizontal and vertical content reflection, including editable text baselines and already rasterized backgrounds
  • Shapes → Rectangle / Oval / Polygon (star, polygon, and vector paths), with corner radii Line shapes preserve native paint as diagnosed images instead of native paths.
  • Fills → solid RGB/CMYK, spot colors (as IDML spot swatches with tint), linear and radial gradients; varying stop alpha becomes a native InDesign Gradient Feather
  • Strokes → native width, color, position and miter/round/bevel joins; patterned contours and nondefault open-path caps become diagnosed images
  • Images → embedded raster (PNG/JPEG/…) and SVG, with crop scale/translation/rotation and flips, in InDesign's native pixel-space geometry
  • Text → per-run fonts, weights, styles, colors, sizes, case, tracking/letter spacing, underline/strikethrough (style, weight, offset, color), alignment, per-paragraph leading, paragraph spacing, and lists
  • Blend modes shared with IDML (Multiply, Screen, Overlay, …) map by name
  • Effects/blur → the block's rendered appearance, including its true contour, stroke and shadow, baked into an embedded image
  • Groups, page background fills, opacity, drop shadows, rotation and flips

Fonts are referenced by family name — InDesign substitutes families that are not installed on the opening machine. Images are always embedded, so packages are self-contained.

Node.js exports read local file:// images and fonts, as well as custom resource schemes resolved by the engine. Browser exports use resolved network, data or buffer resources.

Text remains editable when IDML can preserve its paints. Independent translucent glyph fills and outlines, mixed run opacity, and conflicting background or decoration paints require a rendered PNG. This fallback preserves stroke overflow, rotation and reflections on a transparent page canvas, at four pixels per point up to 2600 pixels on its longest side. Object opacity and blending remain separate. The exporter reports this loss of text editability with TEXT_PAINT_RASTERIZED.

Overline uses this full appearance fallback with TEXT_DECORATION_RASTERIZED, preserving mixed decorations and line styles. Underline and strikethrough remain editable, including decoration ranges after emoji and combining sequences. Hidden objects retain their embedded pixels and exported visibility, so revealing a baked object restores its rendered content.

Visible text range backgrounds use this fallback with TEXT_RANGE_BACKGROUND_RASTERIZED, preserving highlight coverage across styled runs and line breaks. A block-level background stays a separate native rectangle and does not acquire the text's glyph shadow.

Lowercase and titlecase become editable normal text only when the warmed native renderer confirms the same visible case. Font-fallback boundaries can change that case; these frames preserve their actual rendered appearance with TEXT_CASE_RASTERIZED. Intentionally clipped frames retain their fixed size and their clipping when imported again.

Superscript and subscript also use this image fallback, with TEXT_SCRIPT_RASTERIZED, because font-specific scale and baseline shifts cannot be reproduced reliably by InDesign's script defaults. Effects use the same transparent canvas so strokes retain their actual shape and placement. Spot gradient stops and shadow colors use native Tint swatches, and spot underlines retain their separate tint; these paints remain editable in InDesign. Tinted CMYK shadows also retain their ink strength, with the reader resolving their appearance through the native color profile. CMYK fills, outlines, text backgrounds, glyph colors and underlines retain their separate tint attributes too.

SDK 1.81's native shadow renderer paints a named spot at full ink even when its stored color has a partial tint. IDML preserves the public color/tint contract. Its minimum-version regression compares against an independently authored literal RGB shadow; current native rendering matches that same reference exactly.

Linear gradients with coincident handles render as the terminal stop's solid color. They retain that paint and its fill transparency as an editable solid, with DEGENERATE_GRADIENT_AS_SOLID reporting the style conversion. Very short positive spans keep nonzero gradient and feather lengths in the XML.

Shadows with different horizontal and vertical blur radii use the same full appearance fallback and report SHADOW_RASTERIZED. Shadow blur outside Adobe's 0..144 point range uses the complete-paint fallback and reports SHADOW_SIZE_RASTERIZED. Values inside the range, including 144 points, remain editable when the shadow is unclipped and symmetric. Failed effects/blur rendering reports EFFECTS_BAKE_FAILED instead of silently discarding the paint. Each shadow offset is converted to points before checking Adobe's inclusive -1000..1000 range. Visible shadows outside either axis's range preserve full paint with SHADOW_OFFSET_RASTERIZED; if rendering fails, the unsupported shadow is omitted with SHADOW_OFFSET_RASTERIZATION_FAILED. Valid individual offsets remain editable, including a diagonal distance greater than 1000 points. Mixed-direction paragraphs select their base direction from the first strong character, while retaining the World-Ready composer for shaping. Paragraph leading uses each character range's own font metrics and size with the paragraph's line-height multiplier, including styled paragraph breaks. Compatible mixed fonts remain editable. If native layout combines one font's ascender with another font's descender beyond every individual character's leading, TEXT_LEADING_RASTERIZED preserves line placement through the full appearance fallback. Disabled font-pair kerning is retained as an explicit numeric zero override, without changing tracking or ligatures. Text containing literal tabs preserves the runtime's actual tab placement through the full appearance fallback with TEXT_TABS_RASTERIZED. The native global tab rule and its first-run font dependence cannot be retained by portable editable paragraph tab stops. Text without tabs stays editable; the exporter does not change editor-wide tab settings. Paragraph gaps also use each paragraph's own font metrics. Mixed-font paragraphs preserve the spacing of their terminal visual line through the full appearance fallback with TEXT_PARAGRAPH_SPACING_RASTERIZED; paragraphs with uniform metrics remain editable. Each paragraph retains its horizontal alignment; Auto follows that paragraph's base direction. Justify preserves justified word spacing with the final line aligned to that direction. Single-line auto-sizing and tracking allowances use the paragraph's alignment, including overrides, to retain its anchor. Spot-color text backgrounds retain their separate tint. Packaged fonts retain valid OpenType table checksums after renaming.

Even-sided polygons retain the engine's native orientation. Rounded polygon, star and vector-path frames use the full appearance fallback and report SHAPE_CORNERS_RASTERIZED; this also preserves rounded image clipping. Text on a path uses this fallback with TEXT_PATH_RASTERIZED, preserving its baseline offset and underside placement. Straight text and unrounded paths remain editable. Percent-encoded data images retain their original bytes. Compound, curved and self-intersecting NonZero paths use this fallback with FILL_RULE_RASTERIZED to retain winding-dependent fill coverage. Simple linear contours where both fill rules paint the same area remain editable.

Paragraph direction uses Unicode 15.1 bidi data; its license notice is included in LICENSE.md.

Round trip with @imgly/idml-importer

Exports are designed to round-trip through @imgly/idml-importer: importing an exported file reproduces the source scene. The test suite pixel-gates this per capability (most at exactly 0.000% difference) and additionally validates every package against Adobe's IDML schema. Round-trip parity requires @imgly/idml-importer >= 2.0.0.

Development

pnpm install
pnpm build          # dist/ (ESM + CJS + bundled .d.ts)
pnpm test           # round trip + synthetic + capability + schema suites
pnpm test:unit      # pure unit tests

Three suites need external inputs and are opt-in:

  • Fixture round trip — the IDML fixture corpus from imgly/ubq (packages/idml-importer/src/test/examples, git LFS): set IMGLY_IDML_FIXTURES_DIR.
  • Importer parity — @imgly/idml-importer >= 2.0.0, or IMGLY_IMPORTER_PAIRED=1 with a linked development importer.
  • InDesign verification — run scripts/check-capabilities-indesign.sh on macOS with InDesign, then IMGLY_INDESIGN_RENDERS_DIR=<indesign-pages> pnpm test:indesign.

CI runs the self-contained suites: unit tests plus building the 21-capability matrix, exporting it, and validating it against Adobe's RELAX NG schema with jing.

License

See LICENSE.md. A valid CE.SDK license is required — get one at img.ly.