Browser-side utilities for exporting structured note data as PNG images.
- Feature Overview
- Status
- Install
- Quick Start
- API
- Behavior Notes
- Local Development
- Publish Checklist
- Not Included
This package focuses on one job: turn note-shaped data into a polished PNG image in the browser.
It currently provides:
- Off-screen note rendering with isolated styles
- PNG export through
html-to-image - Clipboard-first export with download fallback
- Checklist, labels, tables, code blocks, and image grid rendering
- App-level adapters for rich text rendering and image URL resolution
- Ready to publish as a standalone npm package
- Current package name is
@chenkunqing/note-image-export - Repository metadata points to the public standalone repository
- Version
0.1.1is the first version intended to correct the original private-monorepo metadata from0.1.0
npm install @chenkunqing/note-image-export html-to-imageWhy html-to-image is installed separately:
- this package uses it at runtime
- it is declared as a peer dependency so the consuming app stays in control of the exact version
import { exportNoteAsImage } from '@chenkunqing/note-image-export';
await exportNoteAsImage(
{
title: 'Weekly review',
content: '<p>Ship the package.</p>',
type: 'text',
updatedAt: new Date().toISOString(),
labels: [{ name: 'work' }],
},
{
filename: 'weekly-review',
renderContent: (content) => content,
footerSource: 'My App',
},
);Renders a note and then:
- copies it to the clipboard when supported and preferred
- otherwise downloads it as a
.png
Common options:
filename: download filename without or with.pngrenderContent: render app-specific rich text into HTMLresolveImageSrc: map your stored image object to a usable browser URLupdatedAtLabel: customize the metadata label shown near the headerexportedAtLabel: customize the footer timestamp labelfooterSource: add an app name or brand in the footerpreferClipboard: disable clipboard behavior and always download whenfalse
Renders the same visual note output but returns a PNG Blob instead of copying or downloading it.
Use this when you want to:
- upload the generated image
- attach it to a share sheet
- pipe it into your own download flow
- run app-specific post-processing
type NoteExportData = {
title?: string;
content?: string;
type: 'text' | 'checklist';
color?: string;
updatedAt?: string;
checklistItems?: Array<{ content: string; isChecked: boolean }>;
labels?: Array<{ name: string }>;
images?: Array<{
filename?: string;
localUrl?: string;
src?: string;
alt?: string;
}>;
};Notes:
contentis only used fortype: 'text'checklistItemsis only used fortype: 'checklist'imagescan come from direct browser URLs or app-specific identifiers resolved throughresolveImageSrc
type ExportNoteImageOptions = {
filename?: string;
width?: number;
baseFontSize?: number;
pixelRatio?: number;
backgroundColor?: string;
updatedAtLabel?: string;
exportedAtLabel?: string;
footerSource?: string;
preferClipboard?: boolean;
skipFonts?: boolean;
imagePlaceholder?: string;
formatDate?: (iso: string) => string;
isMobile?: () => boolean;
renderContent?: (content: string, note: NoteExportData) => string;
resolveImageSrc?: (image: NoteExportImage, note: NoteExportData) => string | null | undefined;
};- This package is browser-only. It needs
window,document, and the Clipboard API if you want copy-to-clipboard behavior. - Rich text rendering is intentionally pluggable. Pass
renderContentif your editor stores HTML or Markdown in an app-specific format. - Image source resolution is also pluggable through
resolveImageSrc. - If clipboard copy is unavailable, the export automatically falls back to download.
- The package ships with note-oriented default styles, but intentionally avoids coupling to React, Vite, Zustand, Tiptap, or any backend API format.
npm install
npm run build
npm run check
npm run pack:preview- Update
versioninpackage.json. - Confirm
name,repository,homepage, andbugsare correct for the target repo. - Run
npm run prepublishOnly. - Publish with
npm publish --access public.
This package does not currently include:
- React components
- editor integrations
- state management
- upload APIs
- note persistence
Those should stay in the consuming app and be connected through adapters such as renderContent and resolveImageSrc.