Summernote Gallery is a standalone Summernote 0.9.x plugin for selecting images from a backend-agnostic source adapter and inserting semantic gallery markup into the editor. It can be composed by Summernote Bricks, but Summernote Bricks is not required.
The public master branch contains the 3.0.0-rc.1 source/package contract. Gallery v3 no longer depends on the historical URL/pagination configuration model or the old shared SNB runtime described by earlier documentation.
The maintained ecosystem compatibility matrix validates Gallery with Summernote 0.9.1 across BS3, BS4, BS5 and Lite builds under Chromium, Firefox and WebKit.
Package publication is separate from source readiness. Verify the registry version you intend to consume instead of assuming the v3 RC has been published.
- standalone
summernoteGallerytoolbar plugin; - backend-agnostic
GallerySourceAdaptercontract; - optional host-provided
GalleryUploadAdapterfor multi-file uploads; - asynchronous search with abort support;
- source-only media type and creation-date filtering;
- accessible Grid/Gallery view modes;
- source-only folder paths with accessible exact-folder navigation;
- multi-select image insertion;
- create and edit through a Summernote-native dialog;
- undo-aware edits through Summernote commands;
- accessible search/status/error/listbox semantics;
- clean semantic persisted HTML marked with
data-snb-brick="gallery"anddata-snb-version="3"; - explicit, opt-in helpers for migrating legacy Gallery markup;
- browser-friendly, ESM, CommonJS and TypeScript package artifacts.
For a normal script-tag integration, use the browser-friendly file. You do not need to know or use the CommonJS filename:
<script src="path/to/jquery.js"></script>
<script src="path/to/summernote.js"></script>
<script src="path/to/summernote-gallery/dist/summernote-gallery.browser.js"></script>Configure a source adapter and add summernoteGallery to the toolbar:
const source = {
async list({ query, filters, signal }) {
const params = new URLSearchParams();
if (query) params.set('q', query);
if (filters?.mediaType) params.set('mediaType', filters.mediaType);
if (filters?.createdFrom) params.set('createdFrom', filters.createdFrom);
if (filters?.createdTo) params.set('createdTo', filters.createdTo);
const response = await fetch(`/api/images?${params}`, { signal });
const data = await response.json();
return {
items: data.items.map((image) => ({
id: image.id,
src: image.url,
alt: image.alt,
title: image.title,
caption: image.caption,
createdAt: image.createdAt,
mediaType: image.mediaType,
path: image.path
})),
nextCursor: data.nextCursor
};
}
};
$('#summernote').summernote({
toolbar: [['extensions', ['summernoteGallery']]],
summernoteGallery: {
buttonLabel: 'Gallery',
tooltip: 'Insert gallery',
dialogTitle: 'Image gallery',
saveText: 'Insert',
searchLabel: 'Search images',
searchText: 'Search',
defaultView: 'grid',
source
}
});Gallery works completely on its own. Install Summernote Bricks only if you want to group this button with Heading or other Summernote buttons inside one dropdown.
For static data, the module API also exposes createStaticGallerySource(images).
The package keeps separate artifacts for browsers and build tools:
dist/summernote-gallery.browser.js simple script-tag browser entrypoint
dist/index.js ESM
dist/index.umd.cjs CommonJS / compatibility bundle
dist/types/index.d.ts TypeScript declarations
Host peer dependencies:
{
"jquery": ">=3.6.0 <4",
"summernote": ">=0.9.1 <0.10"
}A source adapter implements:
interface GallerySourceAdapter {
list(request: {
query?: string;
filters?: {
mediaType?: string;
createdFrom?: string;
createdTo?: string;
};
cursor?: string;
signal?: AbortSignal;
}): Promise<{
items: GallerySourceImage[];
nextCursor?: string;
}>;
}GallerySourceImage extends the persisted image model with optional source-only metadata such as createdAt, mediaType and path. These fields can drive filtering and folder navigation but are not written into persisted Gallery HTML.
This keeps Gallery independent from a specific REST shape, CMS, storage provider or backend framework. Hosts normalize their own API into the Gallery model.
Upload controls appear only when the host supplies summernoteGallery.upload. Gallery does not know or require an endpoint, storage provider, authentication scheme or server framework.
const upload = {
async upload(files, signal) {
const body = new FormData();
files.forEach((file) => body.append('images', file));
const response = await fetch('/api/images', {
method: 'POST',
body,
signal
});
const data = await response.json();
return data.items.map((image) => ({
id: image.id,
src: image.url,
alt: image.alt,
title: image.title,
caption: image.caption
}));
}
};
$('#summernote').summernote({
toolbar: [['extensions', ['summernoteGallery']]],
summernoteGallery: { source, upload }
});The adapter receives the selected File[] and an AbortSignal. Returned images are normalized, added to the current result set and selected for insertion. Closing or destroying the dialog aborts in-flight uploads. File objects, credentials and transport state are never persisted by Gallery.
A source image can provide a normalized relative path, for example:
{
id: 'mountain',
src: '/images/mountain.jpg',
alt: 'Mountain',
path: 'nature/alps/mountain.jpg'
}Gallery derives a deterministic folder tree from these paths. When folders exist, the dialog exposes accessible root, parent and child navigation controls and shows only images belonging directly to the selected folder. Selection state is preserved while navigating.
Searches and completed uploads reset navigation to the root so new results remain visible. Folder paths and navigation state are editor-only; path never becomes part of the persisted Gallery HTML.
The source module exports normalizeGalleryPath, buildGalleryFolderTree, galleryFolderPath, filterGalleryImagesByFolder and findGalleryFolderNode for hosts that need the same deterministic folder semantics outside the dialog.
Gallery v3 stores semantic HTML rather than opaque runtime JSON, remote-response configuration or editor controls. Content helpers normalize image data and render/parse the persisted gallery structure.
Source-only metadata (createdAt, mediaType, path), upload files, transport state and folder controls are intentionally excluded from persisted content.
Legacy conversion remains explicit and opt-in so loading an editor does not silently rewrite stored content.
The module entry exports the Summernote plugin, gallery content helpers and source-adapter helpers. Typical integrations can import adapter types or createStaticGallerySource and then configure the normal Summernote plugin lifecycle.
The browser bundle self-registers summernoteGallery when loaded after Summernote.
npm ci
npm run checknpm run check performs strict TypeScript checking, Vitest tests, Vite/TypeScript builds and package-shape validation. The cross-repository Bricks compatibility harness additionally tests the packed Gallery artifact against the supported Summernote/browser matrix.
The maintained reference is Summernote 0.9.1 with:
- Bootstrap 3 build;
- Bootstrap 4 build;
- Bootstrap 5 build;
- Summernote Lite;
- Chromium, Firefox and WebKit.
The historical 0.8.18 demos, old dist/snb-gallery-brick.min.js path and URL/pagination options are legacy references, not the v3 contract.
summernote-gallery— this standalone backend-agnostic Gallery plugin;summernote-heading— standalone semantic Heading plugin;summernote-bricks— optional composer that groups registered plugin buttons;SNB-components— independent optional shared core; Gallery does not currently depend on it.
See the Summernote Bricks roadmap issue #3 for ecosystem release-readiness status.
See CONTRIBUTING.md, SECURITY.md and RELEASING.md.
MIT — see LICENSE.