@enslo/sd-metadata 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +428 -0
- package/README.ja.md +9 -23
- package/README.md +10 -24
- package/dist/index.d.ts +4 -2
- package/dist/index.global.js +7 -7
- package/dist/index.js +467 -222
- package/dist/index.js.map +1 -1
- package/docs/types.ja.md +799 -0
- package/docs/types.md +799 -0
- package/package.json +11 -13
- package/LICENSE +0 -21
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [2.2.0] - 2026-02-27
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Draw Things parser** (#181): Read and write metadata from [Draw Things](https://drawthings.ai/) (macOS/iOS) generated images
|
|
13
|
+
- Extract generation parameters from XMP (Adobe XML Metadata) packets
|
|
14
|
+
- Native XMP read/write for JPEG (APP1 segment) and WebP (XMP chunk)
|
|
15
|
+
- XMP reading from PNG iTXt chunks
|
|
16
|
+
|
|
17
|
+
### Potentially Breaking Changes
|
|
18
|
+
|
|
19
|
+
- **New `GenerationSoftware` member** (#181): `'draw-things'` added. TypeScript users with exhaustive `switch` or `Record<GenerationSoftware, ...>` will need to handle the new value.
|
|
20
|
+
- **New `MetadataSegmentSource` variant** (#181): `{ type: 'xmpPacket' }` added for XMP segment tracking. Exhaustive patterns on `MetadataSegmentSource` will need updating.
|
|
21
|
+
|
|
22
|
+
### Security
|
|
23
|
+
|
|
24
|
+
- **XMP regex ReDoS protection** (#181): Add 64KB size limit on XMP text input to prevent exponential backtracking on malformed XML
|
|
25
|
+
- **XML entity decoder hardening** (#181): Catch `RangeError` from `String.fromCodePoint` on invalid Unicode code points in XMP entities
|
|
26
|
+
- **JPEG COM segment overflow guard** (#181): Add 64KB size limit check to `buildComSegment`, matching the existing guard on `buildXmpApp1Segment`
|
|
27
|
+
|
|
28
|
+
### Maintenance
|
|
29
|
+
|
|
30
|
+
- Update development dependencies
|
|
31
|
+
|
|
32
|
+
## [2.1.1] - 2026-02-24
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- **Malformed input hardening** (#163): Add defensive checks for corrupted or malicious binary data across all format readers and writers
|
|
37
|
+
- PNG writer: validate chunk boundaries before slicing
|
|
38
|
+
- EXIF reader: early bailout for implausibly large tag data sizes
|
|
39
|
+
- JPEG reader: minimum segment length validation for APP1 and COM markers
|
|
40
|
+
- WebP reader: fix off-by-one in chunk iteration boundary check
|
|
41
|
+
- A1111 parser: input length guard for settings regex
|
|
42
|
+
|
|
43
|
+
### Maintenance
|
|
44
|
+
|
|
45
|
+
- Migrate to standard monorepo structure (#160)
|
|
46
|
+
- Use standard APIs for binary operations (#162)
|
|
47
|
+
|
|
48
|
+
## [2.1.0] - 2026-02-22
|
|
49
|
+
|
|
50
|
+
### Added
|
|
51
|
+
|
|
52
|
+
- **IIFE build for userscript support** (#157): Add `dist/index.global.js` (minified IIFE bundle) that exposes a `sdMetadata` global variable, enabling userscripts (Tampermonkey, Violentmonkey, etc.) to load the library via `@require`
|
|
53
|
+
|
|
54
|
+
## [2.0.1] - 2026-02-19
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- **ComfyUI DetailerForEach support** (#150): Extract prompt, negative prompt, and sampling settings from workflows using `DetailerForEach` (ComfyUI Impact Pack inpainting/detailer nodes)
|
|
59
|
+
- **ComfyUI SamplerCustom support** (#150): Extract metadata from `SamplerCustom` nodes with dedicated handling for its input layout (cfg on node, noise_seed via reference, steps/scheduler from BasicScheduler)
|
|
60
|
+
- **ComfyUI conditioning chain traversal** (#150): Follow conditioning through intermediate nodes (e.g. ControlNet apply) to reach CLIPTextEncode for prompt text extraction
|
|
61
|
+
|
|
62
|
+
## [2.0.0] - 2026-02-19
|
|
63
|
+
|
|
64
|
+
### ⚠️ Breaking Changes
|
|
65
|
+
|
|
66
|
+
- **Forge family software identifiers** (#129): The `'forge'` identifier now refers specifically to the current [Forge](https://github.com/lllyasviel/stable-diffusion-webui-forge) main line. Images previously detected as `'forge'` (which was a catch-all for all `f`-prefixed versions) are now split into distinct identifiers:
|
|
67
|
+
|
|
68
|
+
| v1.x `software` | v2.0.0 `software` | Tool |
|
|
69
|
+
| --- | --- | --- |
|
|
70
|
+
| `'forge'` | `'forge'` | [Forge](https://github.com/lllyasviel/stable-diffusion-webui-forge) (current main line) |
|
|
71
|
+
| `'forge'` | `'forge-classic'` | [Forge Classic](https://github.com/Haoming02/sd-webui-forge-classic/tree/classic) |
|
|
72
|
+
| `'forge'` | `'reforge'` | [reForge](https://github.com/Panchovix/stable-diffusion-webui-reForge) |
|
|
73
|
+
| `'forge'` | `'easy-reforge'` | [EasyReforge](https://github.com/Zuntan03/EasyReforge) |
|
|
74
|
+
|
|
75
|
+
If your code checks `metadata.software === 'forge'`, update it to handle the new identifiers. TypeScript users with exhaustive `switch` statements on `GenerationSoftware` will see compile errors for the new values.
|
|
76
|
+
|
|
77
|
+
### Added
|
|
78
|
+
|
|
79
|
+
- **`embed()` function** (#126): Write metadata in SD WebUI (A1111) format to any supported image
|
|
80
|
+
- Unlike `write()` (which preserves the original format), `embed()` always writes in A1111 plain-text format
|
|
81
|
+
- Accepts user-created `EmbedMetadata` or parsed `GenerationMetadata` directly
|
|
82
|
+
- Optional `extras` field on `EmbedMetadata` for arbitrary key-value pairs in the settings line (e.g., `Version`, `Lora hashes`)
|
|
83
|
+
- Extras override structured fields at their original position; new keys append at the end
|
|
84
|
+
- Supports PNG (tEXt/iTXt), JPEG (Exif), and WebP (Exif)
|
|
85
|
+
- **`stringify()` function** (#125): Unified metadata formatting for display
|
|
86
|
+
- Accepts `ParseResult`, `GenerationMetadata`, or `EmbedMetadata` directly
|
|
87
|
+
- `ParseResult`: `success` → SD WebUI format, `unrecognized` → raw text, `empty`/`invalid` → empty string
|
|
88
|
+
- `GenerationMetadata` / `EmbedMetadata`: directly formats as SD WebUI text
|
|
89
|
+
- **`softwareLabels` constant**: Read-only mapping from `GenerationSoftware` identifiers to human-readable display names
|
|
90
|
+
- **`EmbedMetadata` type**: User-created custom metadata — `BaseMetadata & Pick<NovelAIMetadata, 'characterPrompts'> & { extras? }`
|
|
91
|
+
- **`BaseMetadata` type export**: Previously internal, now available for direct use
|
|
92
|
+
- **`GenerationSoftware` type export**: String literal union of all supported software identifiers
|
|
93
|
+
|
|
94
|
+
### Fixed
|
|
95
|
+
|
|
96
|
+
- **TensorArt parser** (#138): Extract sampler and scheduler from the ComfyUI node graph. Previously these fields were missing because `generation_data` does not contain them.
|
|
97
|
+
- **ComfyUI CLIP skip** (#137): Extract `clipSkip` from the `CLIPSetLastLayer` node. Previously, CLIP skip was silently dropped from all ComfyUI-based tool output (ComfyUI, TensorArt, Stability Matrix).
|
|
98
|
+
- **Fooocus parser** (#130): Rewrite based on actual Fooocus source code analysis. The previous implementation was non-functional due to reading from the wrong metadata location. Now supports both JSON and A1111 text metadata schemes.
|
|
99
|
+
- **Easy Diffusion parser** (#131): Improved based on source code analysis. Removed phantom key format that never appeared in actual images, improved detection reliability, and added upscale/denoise field extraction.
|
|
100
|
+
|
|
101
|
+
### Changed
|
|
102
|
+
|
|
103
|
+
- **SD WebUI family detection** (#129): Explicit Version-field pattern matching for SD WebUI (`v` + digit) and all Forge variants. Added real SD WebUI sample files, promoting Stable Diffusion WebUI from experimental to fully supported.
|
|
104
|
+
|
|
105
|
+
### Deprecated
|
|
106
|
+
|
|
107
|
+
- **`writeAsWebUI()`**: Use `embed()` instead (now a thin wrapper around `embed()`)
|
|
108
|
+
- **`formatAsWebUI()`**: Use `stringify()` instead (now a thin wrapper around internal `buildEmbedText()`)
|
|
109
|
+
- **`formatRaw()`**: Use `stringify()` instead
|
|
110
|
+
|
|
111
|
+
### Migration Guide
|
|
112
|
+
|
|
113
|
+
| v1.x | v2.0.0 | Notes |
|
|
114
|
+
| ------------------------------- | ------------------------ | ----------------------------------------- |
|
|
115
|
+
| `writeAsWebUI(image, metadata)` | `embed(image, metadata)` | Also accepts user-created `EmbedMetadata` |
|
|
116
|
+
| `formatAsWebUI(metadata)` | `stringify(metadata)` | Also accepts `ParseResult` directly |
|
|
117
|
+
| `formatRaw(raw)` | `stringify(readResult)` | Handles all statuses automatically |
|
|
118
|
+
| `software === 'forge'` | Check all Forge variants | See Breaking Changes above |
|
|
119
|
+
|
|
120
|
+
## [1.8.1] - 2026-02-15
|
|
121
|
+
|
|
122
|
+
### Fixed
|
|
123
|
+
|
|
124
|
+
- **A1111 detection criteria** (#122): Fix `writeAsWebUI` round-trip for minimal metadata (no sampling settings)
|
|
125
|
+
- Detection now accepts `Steps:` OR `Sampler:` OR `Negative prompt:` (was requiring both `Steps:` AND `Sampler:`)
|
|
126
|
+
|
|
127
|
+
### Changed
|
|
128
|
+
|
|
129
|
+
- **Unify detection and parsing responsibilities** (#122): `detectSoftware()` is now the single source of truth for format identification
|
|
130
|
+
- Remove redundant detection guards from parsers (a1111, novelai, comfyui, fooocus, ruined-fooocus)
|
|
131
|
+
- Remove fallback parser chain from router
|
|
132
|
+
|
|
133
|
+
## [1.8.0] - 2026-02-14
|
|
134
|
+
|
|
135
|
+
### Added
|
|
136
|
+
|
|
137
|
+
- **ComfyUI SamplerCustomAdvanced support** (#118): Parse distributed node workflows
|
|
138
|
+
- Trace sampling parameters across RandomNoise, CFGGuider, KSamplerSelect, and BasicScheduler nodes
|
|
139
|
+
- Support UNETLoader as alternative model loader (fallback from CheckpointLoaderSimple)
|
|
140
|
+
- Resolve hires scale from rgthree node references (`clip_scale`)
|
|
141
|
+
- **HF Space upscale settings** (#119): Extract `use_upscaler` as hires settings
|
|
142
|
+
- `upscale_method` → `hires.upscaler`
|
|
143
|
+
- `upscaler_strength` → `hires.denoise`
|
|
144
|
+
- `upscale_by` → `hires.scale`
|
|
145
|
+
|
|
146
|
+
### Changed
|
|
147
|
+
|
|
148
|
+
- **Bundle size optimization** (#117): Internal refactoring to reduce bundle size and consolidate codebase (no public API changes)
|
|
149
|
+
|
|
150
|
+
## [1.7.1] - 2026-02-01
|
|
151
|
+
|
|
152
|
+
### Fixed
|
|
153
|
+
|
|
154
|
+
- **PNG chunk encoding strategies** (#114): Corrected encoding for format conversion
|
|
155
|
+
- saveimage-plus and CivitAI now use Unicode escape encoding (was incorrectly using raw UTF-8)
|
|
156
|
+
- Stability Matrix and TensorArt now use per-chunk encoding to match original behavior
|
|
157
|
+
- `parameters` (Stability Matrix) and `generation_data` (TensorArt) use raw UTF-8
|
|
158
|
+
- Other chunks use Unicode escape encoding
|
|
159
|
+
- This ensures Japanese and other non-ASCII characters are correctly preserved during round-trip conversion
|
|
160
|
+
|
|
161
|
+
## [1.7.0] - 2026-02-01
|
|
162
|
+
|
|
163
|
+
### Added
|
|
164
|
+
|
|
165
|
+
- **ComfyUI extended node support** (#108): Support for additional custom nodes
|
|
166
|
+
- **Prompt nodes**: Power Prompt (rgthree), DF_Text_Box (Derfuu)
|
|
167
|
+
- **Latent nodes**: SDXL Empty Latent Image (rgthree)
|
|
168
|
+
- **Seed nodes**: CR Seed
|
|
169
|
+
- **Hires detection**: LatentUpscale, LatentUpscaleBy
|
|
170
|
+
- **InvokeAI upscale settings** (#109): Extract upscale information from InvokeAI images
|
|
171
|
+
- `upscale.upscaler`: Upscaler model name (e.g., RealESRGAN_x4plus_anime_6B)
|
|
172
|
+
- `upscale.scale`: Scale factor
|
|
173
|
+
- **ComfyUI denoise in SamplingSettings** (#110): Extract denoising strength from KSampler nodes
|
|
174
|
+
- Only captured when `denoise < 1.0` (img2img workflows)
|
|
175
|
+
- `denoise = 1.0` (txt2img default) is omitted
|
|
176
|
+
|
|
177
|
+
### Changed
|
|
178
|
+
|
|
179
|
+
- **Internal refactoring** (#107): Type cleanup and developer experience improvements (no public API changes)
|
|
180
|
+
|
|
181
|
+
## [1.6.1] - 2026-01-29
|
|
182
|
+
|
|
183
|
+
### Fixed
|
|
184
|
+
|
|
185
|
+
- **CivitAI Orchestration JPEG→PNG conversion** (#102): Store all metadata in a single `prompt` chunk instead of separating into multiple chunks, improving round-trip compatibility
|
|
186
|
+
- This fixes an issue introduced in v1.6.0 where the chunk structure was not optimal
|
|
187
|
+
|
|
188
|
+
## [1.6.0] - 2026-01-29
|
|
189
|
+
|
|
190
|
+
### Added
|
|
191
|
+
|
|
192
|
+
- **`strict` option for `read()`** (#95): Control dimension extraction behavior
|
|
193
|
+
- When `true`, dimensions come strictly from metadata only (returns 0 if not present)
|
|
194
|
+
- When `false` (default), missing dimensions fall back to image headers
|
|
195
|
+
|
|
196
|
+
### Fixed
|
|
197
|
+
|
|
198
|
+
- **CivitAI detection and format conversion** (#96): CivitAI images are now correctly detected and can be converted between formats
|
|
199
|
+
- Previously, CivitAI Orchestration images were incorrectly detected as ComfyUI or SD WebUI
|
|
200
|
+
- Images using Hires fix or Upscaler on CivitAI now convert to PNG correctly (previously became `unrecognized`)
|
|
201
|
+
|
|
202
|
+
### Changed
|
|
203
|
+
|
|
204
|
+
- **Parser refactoring** (#96, #98): Improved code quality across all parsers
|
|
205
|
+
- Immutable patterns for better maintainability
|
|
206
|
+
- Function decomposition for ComfyUI parser
|
|
207
|
+
|
|
208
|
+
## [1.5.0] - 2026-01-26
|
|
209
|
+
|
|
210
|
+
### Added
|
|
211
|
+
|
|
212
|
+
- **ArrayBuffer support** (#89): All public API functions (`read`, `write`, `writeAsWebUI`) now accept both `Uint8Array` and `ArrayBuffer` as input
|
|
213
|
+
- Browser users can pass `ArrayBuffer` directly from `File.arrayBuffer()` or `fetch().arrayBuffer()` without manual conversion
|
|
214
|
+
- Node.js `Buffer` (which extends `Uint8Array`) continues to work as before
|
|
215
|
+
|
|
216
|
+
## [1.4.2] - 2026-01-25
|
|
217
|
+
|
|
218
|
+
### Fixed
|
|
219
|
+
|
|
220
|
+
- **JPEG/WebP Format Conversion** (#85): Fixed metadata parsing for HF-Space, Ruined Fooocus, TensorArt, and Stability Matrix after cross-format conversion (PNG ↔ JPEG/WebP)
|
|
221
|
+
- HF-Space and Ruined Fooocus: Now correctly parsed from Comment JSON (was `unrecognized`)
|
|
222
|
+
- TensorArt and Stability Matrix: Now correctly detected from Comment JSON (was misidentified as `comfyui`)
|
|
223
|
+
- **Unicode Round-trip** (#85): Non-ASCII characters (e.g., Japanese) are now preserved during PNG → JPEG/WebP → PNG conversions
|
|
224
|
+
|
|
225
|
+
### Changed
|
|
226
|
+
|
|
227
|
+
- **Internal Refactoring** (#86): Removed unused `exifSoftware` and `exifDocumentName` support (no public API changes). These Exif tags were not populated in real NovelAI files.
|
|
228
|
+
|
|
229
|
+
## [1.4.1] - 2026-01-24
|
|
230
|
+
|
|
231
|
+
### Fixed
|
|
232
|
+
|
|
233
|
+
- **NovelAI WebP Data Loss** (#79): Fixed an issue where `Software` and `Title` (DocumentName) tags were lost when converting NovelAI images to WebP. They are now correctly preserved in Exif tags.
|
|
234
|
+
- **NovelAI Version Detection** (#79): Improved detection of NovelAI version strings to better support newer versions.
|
|
235
|
+
|
|
236
|
+
### Changed
|
|
237
|
+
|
|
238
|
+
- **Internal Refactoring** (#80): Decoupled encoding strategies from specific tool names for better maintainability (no public API changes).
|
|
239
|
+
|
|
240
|
+
## [1.4.0] - 2026-01-24
|
|
241
|
+
|
|
242
|
+
### ⚠️ BREAKING CHANGES
|
|
243
|
+
|
|
244
|
+
- **Remove `force` option from `write()`** (#76): Blind conversion for unrecognized formats is no longer supported.
|
|
245
|
+
- **Metadata drop behavior**: When converting unrecognized metadata to a different format (e.g., PNG → JPEG), metadata is now dropped instead of attempting a blind conversion.
|
|
246
|
+
|
|
247
|
+
### Added
|
|
248
|
+
|
|
249
|
+
- **`WriteWarning` type** (#76): Notifies when metadata was intentionally dropped during conversion (e.g., unrecognized cross-format).
|
|
250
|
+
- **Graceful unrecognized handling**: Unrecognized metadata is still preserved when writing back to the same format or using `writeAsWebUI` with structured metadata.
|
|
251
|
+
|
|
252
|
+
### Documentation
|
|
253
|
+
|
|
254
|
+
- Updated API examples to use the new `result.warning` pattern.
|
|
255
|
+
|
|
256
|
+
## [1.3.0] - 2026-01-23
|
|
257
|
+
|
|
258
|
+
### Added
|
|
259
|
+
|
|
260
|
+
- **`formatRaw()` function** (#72): Format raw metadata as plain text for display
|
|
261
|
+
- Works with unrecognized metadata (`status: 'unrecognized'`)
|
|
262
|
+
- Multiple entries separated by blank lines
|
|
263
|
+
- Ideal for fallback display when parsing fails
|
|
264
|
+
|
|
265
|
+
### Changed
|
|
266
|
+
|
|
267
|
+
- **Migrate to pnpm** (#74): Replace npm with pnpm for faster, more disk-efficient package management
|
|
268
|
+
- **Upgrade Vitest to v4** (#74): Fix esbuild security vulnerability (GHSA-67mh-4wv8-2f99)
|
|
269
|
+
|
|
270
|
+
### Documentation
|
|
271
|
+
|
|
272
|
+
- Improve README quality and fix package import names (#73)
|
|
273
|
+
- Restructure Usage section with collapsible advanced examples
|
|
274
|
+
- Emphasize `formatAsWebUI` cross-tool normalization capability
|
|
275
|
+
|
|
276
|
+
## [1.2.0] - 2026-01-22
|
|
277
|
+
|
|
278
|
+
### Added
|
|
279
|
+
|
|
280
|
+
- **`writeAsWebUI()` function** (#69): Write any GenerationMetadata to PNG/JPEG/WebP in SD WebUI (A1111) format
|
|
281
|
+
- Create custom metadata from scratch
|
|
282
|
+
- Convert metadata from any tool to WebUI-compatible format
|
|
283
|
+
- Automatic encoding strategy (tEXt for ASCII, iTXt for non-ASCII in PNG)
|
|
284
|
+
- **`formatAsWebUI()` function** (#69): Format metadata as human-readable text in SD WebUI format
|
|
285
|
+
- Tool-agnostic standard format for displaying generation metadata
|
|
286
|
+
- Supports NovelAI character prompts with position comments
|
|
287
|
+
- Normalizes line endings for cross-platform compatibility
|
|
288
|
+
|
|
289
|
+
## [1.1.1] - 2026-01-21
|
|
290
|
+
|
|
291
|
+
### Documentation
|
|
292
|
+
|
|
293
|
+
- Update README CDN usage example to reference v1.1.0
|
|
294
|
+
- Add README version update step to release workflow
|
|
295
|
+
- Remove trailing slash from package.json homepage URL
|
|
296
|
+
|
|
297
|
+
## [1.1.0] - 2026-01-21
|
|
298
|
+
|
|
299
|
+
### ⚠️ BREAKING CHANGES
|
|
300
|
+
|
|
301
|
+
- **Replace `workflow` with `nodes` in ComfyUIMetadata** (#58): The `workflow?: unknown` field has been replaced with typed `nodes: ComfyNodeGraph`.
|
|
302
|
+
- **What `workflow` was**: ComfyUI UI layout data containing node positions, sizes, link connections, and visual groupings—information used by ComfyUI's graph editor but not required for image reproduction.
|
|
303
|
+
- **What `nodes` is**: The actual node graph (from PNG `prompt` chunk) mapping node IDs to their inputs and class types—the essential data needed to reproduce the generation.
|
|
304
|
+
- **Why this change**: Previously, `workflow` only existed in ComfyUI images and was `undefined` for other ComfyUI-compatible tools (TensorArt, Stability Matrix, SwarmUI). Now `nodes` provides actual node graph data from all tools.
|
|
305
|
+
- **Remove `type` field from GenerationMetadata** (#57): Use `metadata.software` instead of `metadata.type` for type narrowing.
|
|
306
|
+
- **Internal types no longer exported** (#60): `BaseMetadata` and `GenerationSoftware` are now internal types.
|
|
307
|
+
|
|
308
|
+
### Added
|
|
309
|
+
|
|
310
|
+
- **SwarmUI workflow preservation** (#59): Store ComfyUI node graph in `exifMake` segment when converting PNG to JPEG/WebP, enabling complete round-trip preservation
|
|
311
|
+
- **Typed ComfyUI node graph** (#58): New types `ComfyNode`, `ComfyNodeGraph`, `ComfyNodeReference`, `ComfyNodeInputValue` for type-safe workflow access
|
|
312
|
+
- **Expanded type exports** (#60): Export `ModelSettings`, `SamplingSettings`, `HiresSettings`, `UpscaleSettings`, `CharacterPrompt`, and chunk/segment types
|
|
313
|
+
- **Type documentation** (#60): Comprehensive type reference at `docs/types.md`
|
|
314
|
+
|
|
315
|
+
### Fixed
|
|
316
|
+
|
|
317
|
+
- **TensorArt seed extraction** (#61): Extract actual seed from KSampler node when `generation_data.seed` is -1 (random placeholder)
|
|
318
|
+
|
|
319
|
+
### Changed
|
|
320
|
+
|
|
321
|
+
- **Metadata type consolidation** (#60): Renamed `A1111Metadata` to `StandardMetadata`, merged `InvokeAIMetadata` into `StandardMetadata`
|
|
322
|
+
- **ComfyUIMetadata restructure** (#60): Split into `BasicComfyUIMetadata` (nodes required) and `SwarmUIMetadata` (nodes optional)
|
|
323
|
+
|
|
324
|
+
### Documentation
|
|
325
|
+
|
|
326
|
+
- Improved GenerationMetadata documentation in README (#62)
|
|
327
|
+
- Added comprehensive type reference docs (#60)
|
|
328
|
+
- Improved README usage examples (#56)
|
|
329
|
+
|
|
330
|
+
## [1.0.2] - 2026-01-19
|
|
331
|
+
|
|
332
|
+
### Fixed
|
|
333
|
+
|
|
334
|
+
- **Incorrect SD-WebUI Detection**: Fixed false positives where non-AI generated images (e.g., from photo editing software) were incorrectly detected as SD-WebUI/A1111 format (#47)
|
|
335
|
+
- **ComfyUI Detection**: Improved detection for ComfyUI files, fixing cases where valid ComfyUI metadata was not recognized (#47, #50)
|
|
336
|
+
|
|
337
|
+
### Changed
|
|
338
|
+
|
|
339
|
+
- Refactored detection logic with tier-based structure for improved maintainability (#47)
|
|
340
|
+
|
|
341
|
+
## [1.0.1] - 2026-01-13
|
|
342
|
+
|
|
343
|
+
### Changed
|
|
344
|
+
|
|
345
|
+
- Updated package homepage URL to point to the demo site (<https://sd-metadata.pages.dev/>) instead of the GitHub repository
|
|
346
|
+
|
|
347
|
+
## [1.0.0] - 2026-01-13
|
|
348
|
+
|
|
349
|
+
### Added
|
|
350
|
+
|
|
351
|
+
#### Core Features
|
|
352
|
+
|
|
353
|
+
- **Multi-format Support**: PNG (tEXt / iTXt), JPEG (COM / Exif), WebP (Exif)
|
|
354
|
+
- **Unified API**: Simple `read()` and `write()` functions work across all formats
|
|
355
|
+
- **TypeScript Native**: Written in TypeScript with full type definitions included
|
|
356
|
+
- **Zero Dependencies**: Works in Node.js and browsers without any external dependencies
|
|
357
|
+
- **Format Conversion**: Seamlessly convert metadata between PNG, JPEG, and WebP
|
|
358
|
+
- **Lossless Round-trip**: Preserves original metadata structure when converting back to native format
|
|
359
|
+
- Image dimension extraction with automatic fallback from image headers
|
|
360
|
+
|
|
361
|
+
#### Supported AI Tools
|
|
362
|
+
|
|
363
|
+
**Fully Supported** (verified with sample files, native format support):
|
|
364
|
+
|
|
365
|
+
- NovelAI - PNG and WebP native formats
|
|
366
|
+
- ComfyUI - PNG native format
|
|
367
|
+
- Stable Diffusion WebUI (AUTOMATIC1111) - Experimental (no samples yet)
|
|
368
|
+
- Forge / Forge Neo - PNG, JPEG, and WebP native formats
|
|
369
|
+
- InvokeAI - PNG native format
|
|
370
|
+
- SwarmUI - PNG and WebP native formats
|
|
371
|
+
|
|
372
|
+
**Extended Support** (sd-metadata specific parsers, cross-format conversion):
|
|
373
|
+
|
|
374
|
+
- Civitai - Uses A1111-compatible format, JPEG primary format
|
|
375
|
+
- TensorArt - Custom JSON format in PNG
|
|
376
|
+
- Stability Matrix - Custom JSON format in PNG
|
|
377
|
+
- HuggingFace Space - JSON format in Exif
|
|
378
|
+
- Ruined Fooocus - PNG format
|
|
379
|
+
|
|
380
|
+
**Experimental** (implemented from reference code, no sample verification):
|
|
381
|
+
|
|
382
|
+
- Easy Diffusion
|
|
383
|
+
- Fooocus
|
|
384
|
+
|
|
385
|
+
#### Advanced Features
|
|
386
|
+
|
|
387
|
+
- Segment/chunk tracking for lossless round-trip preservation
|
|
388
|
+
- ComfyUI detection priority when both prompt and workflow exist
|
|
389
|
+
- NovelAI WebP UTF-8 corruption auto-correction
|
|
390
|
+
- Force conversion for unrecognized metadata formats with `{ force: true }` option
|
|
391
|
+
|
|
392
|
+
### Known Limitations
|
|
393
|
+
|
|
394
|
+
- **ComfyUI JPEG/WebP**: While reading supports major custom node formats (e.g., `save-image-extended`), writing always uses the `comfyui-saveimage-plus` format for best information preservation and ComfyUI drag-and-drop workflow compatibility
|
|
395
|
+
- **NovelAI WebP**: Auto-corrects corrupted UTF-8 in Description field, breaking content-equivalent round-trip (intentional for data validity)
|
|
396
|
+
- **SwarmUI PNG→JPEG/WebP**: Loses ComfyUI workflow data from `prompt` chunk to match native WebP format (metadata preserved)
|
|
397
|
+
|
|
398
|
+
### Development
|
|
399
|
+
|
|
400
|
+
- Comprehensive test suite with unit, sample, and integration tests
|
|
401
|
+
- Test coverage reporting with Vitest
|
|
402
|
+
- GitHub Actions CI with automated coverage reports
|
|
403
|
+
- Lefthook pre-commit hooks for linting and type checking
|
|
404
|
+
- Biome for code formatting and linting
|
|
405
|
+
- CONTRIBUTING.md for community contributions
|
|
406
|
+
|
|
407
|
+
[2.2.0]: https://github.com/enslo/sd-metadata/releases/tag/core@2.2.0
|
|
408
|
+
[2.1.1]: https://github.com/enslo/sd-metadata/releases/tag/core@2.1.1
|
|
409
|
+
[2.1.0]: https://github.com/enslo/sd-metadata/releases/tag/v2.1.0
|
|
410
|
+
[2.0.1]: https://github.com/enslo/sd-metadata/releases/tag/v2.0.1
|
|
411
|
+
[2.0.0]: https://github.com/enslo/sd-metadata/releases/tag/v2.0.0
|
|
412
|
+
[1.8.1]: https://github.com/enslo/sd-metadata/releases/tag/v1.8.1
|
|
413
|
+
[1.8.0]: https://github.com/enslo/sd-metadata/releases/tag/v1.8.0
|
|
414
|
+
[1.7.1]: https://github.com/enslo/sd-metadata/releases/tag/v1.7.1
|
|
415
|
+
[1.7.0]: https://github.com/enslo/sd-metadata/releases/tag/v1.7.0
|
|
416
|
+
[1.6.1]: https://github.com/enslo/sd-metadata/releases/tag/v1.6.1
|
|
417
|
+
[1.6.0]: https://github.com/enslo/sd-metadata/releases/tag/v1.6.0
|
|
418
|
+
[1.5.0]: https://github.com/enslo/sd-metadata/releases/tag/v1.5.0
|
|
419
|
+
[1.4.2]: https://github.com/enslo/sd-metadata/releases/tag/v1.4.2
|
|
420
|
+
[1.4.1]: https://github.com/enslo/sd-metadata/releases/tag/v1.4.1
|
|
421
|
+
[1.4.0]: https://github.com/enslo/sd-metadata/releases/tag/v1.4.0
|
|
422
|
+
[1.3.0]: https://github.com/enslo/sd-metadata/releases/tag/v1.3.0
|
|
423
|
+
[1.2.0]: https://github.com/enslo/sd-metadata/releases/tag/v1.2.0
|
|
424
|
+
[1.1.1]: https://github.com/enslo/sd-metadata/releases/tag/v1.1.1
|
|
425
|
+
[1.1.0]: https://github.com/enslo/sd-metadata/releases/tag/v1.1.0
|
|
426
|
+
[1.0.2]: https://github.com/enslo/sd-metadata/releases/tag/v1.0.2
|
|
427
|
+
[1.0.1]: https://github.com/enslo/sd-metadata/releases/tag/v1.0.1
|
|
428
|
+
[1.0.0]: https://github.com/enslo/sd-metadata/releases/tag/v1.0.0
|
package/README.ja.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# sd-metadata
|
|
1
|
+
# @enslo/sd-metadata
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@enslo/sd-metadata)
|
|
4
4
|
[](https://www.npmjs.com/package/@enslo/sd-metadata)
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
🌐 **[English version](./README.md)**
|
|
8
8
|
|
|
9
|
+
🔗 **[ライブデモ](https://sd-metadata.pages.dev/)**
|
|
10
|
+
|
|
9
11
|
AI生成画像に埋め込まれたメタデータを読み書きするためのTypeScriptライブラリです。
|
|
10
12
|
|
|
11
13
|
## 特徴
|
|
@@ -45,6 +47,7 @@ npm install @enslo/sd-metadata
|
|
|
45
47
|
| [Fooocus](https://github.com/lllyasviel/Fooocus) | ⚠️ | ⚠️ | ⚠️ |
|
|
46
48
|
| [Ruined Fooocus](https://github.com/runew0lf/RuinedFooocus) | ✅ | 🔄️ | 🔄️ |
|
|
47
49
|
| [Easy Diffusion](https://github.com/easydiffusion/easydiffusion) | ⚠️ | ⚠️ | ⚠️ |
|
|
50
|
+
| [Draw Things](https://drawthings.ai/) | ⚠️ | ⚠️ | ⚠️ |
|
|
48
51
|
|
|
49
52
|
**凡例:**
|
|
50
53
|
|
|
@@ -63,7 +66,7 @@ npm install @enslo/sd-metadata
|
|
|
63
66
|
> \* フォーマット固有の動作があるツール。詳細は[フォーマット固有の動作](#フォーマット固有の動作)を参照してください。
|
|
64
67
|
|
|
65
68
|
> [!TIP]
|
|
66
|
-
> **ツールサポートの拡大にご協力ください!** 実験的なツール(Easy Diffusion、Fooocus)やサポートされていないツールのサンプル画像を募集しています。これらのAIツールで生成したサンプル画像をお持ちの方は、ぜひご提供ください!詳細は[CONTRIBUTING.md](CONTRIBUTING.md)を参照してください。
|
|
69
|
+
> **ツールサポートの拡大にご協力ください!** 実験的なツール(Easy Diffusion、Fooocus)やサポートされていないツールのサンプル画像を募集しています。これらのAIツールで生成したサンプル画像をお持ちの方は、ぜひご提供ください!詳細は[CONTRIBUTING.md](https://github.com/enslo/sd-metadata/blob/main/CONTRIBUTING.md)を参照してください。
|
|
67
70
|
|
|
68
71
|
## フォーマット固有の動作
|
|
69
72
|
|
|
@@ -145,7 +148,7 @@ fileInput.addEventListener('change', async (e) => {
|
|
|
145
148
|
// ==UserScript==
|
|
146
149
|
// @name My Script
|
|
147
150
|
// @namespace https://example.com
|
|
148
|
-
// @require https://cdn.jsdelivr.net/npm/@enslo/sd-metadata@2.
|
|
151
|
+
// @require https://cdn.jsdelivr.net/npm/@enslo/sd-metadata@2.2.0/dist/index.global.js
|
|
149
152
|
// ==/UserScript==
|
|
150
153
|
|
|
151
154
|
const response = await fetch(imageUrl);
|
|
@@ -557,7 +560,8 @@ type GenerationSoftware =
|
|
|
557
560
|
| 'novelai' | 'comfyui' | 'swarmui' | 'tensorart' | 'stability-matrix'
|
|
558
561
|
| 'sd-webui' | 'forge' | 'forge-classic' | 'forge-neo'
|
|
559
562
|
| 'reforge'| 'easy-reforge' | 'sd-next' | 'civitai' | 'hf-space'
|
|
560
|
-
| 'invokeai' | 'easydiffusion' | 'fooocus' | 'ruined-fooocus'
|
|
563
|
+
| 'invokeai' | 'easydiffusion' | 'fooocus' | 'ruined-fooocus'
|
|
564
|
+
| 'draw-things';
|
|
561
565
|
```
|
|
562
566
|
|
|
563
567
|
### `EmbedMetadata`
|
|
@@ -586,25 +590,7 @@ type RawMetadata =
|
|
|
586
590
|
|
|
587
591
|
## 開発
|
|
588
592
|
|
|
589
|
-
|
|
590
|
-
# 依存関係をインストール
|
|
591
|
-
pnpm install
|
|
592
|
-
|
|
593
|
-
# テストを実行
|
|
594
|
-
pnpm test
|
|
595
|
-
|
|
596
|
-
# ビルド
|
|
597
|
-
pnpm build
|
|
598
|
-
|
|
599
|
-
# リント
|
|
600
|
-
pnpm lint
|
|
601
|
-
|
|
602
|
-
# 型チェック
|
|
603
|
-
pnpm typecheck
|
|
604
|
-
|
|
605
|
-
# デモサイト起動
|
|
606
|
-
pnpm demo
|
|
607
|
-
```
|
|
593
|
+
開発のセットアップとガイドラインについては、[コントリビューションガイド](https://github.com/enslo/sd-metadata/blob/main/CONTRIBUTING.md)を参照してください。
|
|
608
594
|
|
|
609
595
|
## ライセンス
|
|
610
596
|
|
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
# sd-metadata
|
|
1
|
+
# @enslo/sd-metadata
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@enslo/sd-metadata)
|
|
4
4
|
[](https://www.npmjs.com/package/@enslo/sd-metadata)
|
|
5
5
|
[](https://github.com/enslo/sd-metadata/blob/main/LICENSE)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
🌐 **[日本語版はこちら](./README.ja.md)**
|
|
8
|
+
|
|
9
|
+
🔗 **[Live Demo](https://sd-metadata.pages.dev/)**
|
|
8
10
|
|
|
9
11
|
A TypeScript library to read and write metadata embedded in AI-generated images.
|
|
10
12
|
|
|
@@ -45,6 +47,7 @@ npm install @enslo/sd-metadata
|
|
|
45
47
|
| [Fooocus](https://github.com/lllyasviel/Fooocus) | ⚠️ | ⚠️ | ⚠️ |
|
|
46
48
|
| [Ruined Fooocus](https://github.com/runew0lf/RuinedFooocus) | ✅ | 🔄️ | 🔄️ |
|
|
47
49
|
| [Easy Diffusion](https://github.com/easydiffusion/easydiffusion) | ⚠️ | ⚠️ | ⚠️ |
|
|
50
|
+
| [Draw Things](https://drawthings.ai/) | ⚠️ | ⚠️ | ⚠️ |
|
|
48
51
|
|
|
49
52
|
**Legend:**
|
|
50
53
|
|
|
@@ -63,7 +66,7 @@ When you convert from a native format to an extended format and back (e.g., PNG
|
|
|
63
66
|
> \* Tools with format-specific behaviors. See [Format-Specific Behaviors](#format-specific-behaviors) for details.
|
|
64
67
|
|
|
65
68
|
> [!TIP]
|
|
66
|
-
> **Help us expand tool support!** We're actively collecting sample images from experimental tools (Easy Diffusion, Fooocus) and unsupported tools. If you have sample images generated by these or other AI tools, please consider contributing them! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
|
69
|
+
> **Help us expand tool support!** We're actively collecting sample images from experimental tools (Easy Diffusion, Fooocus) and unsupported tools. If you have sample images generated by these or other AI tools, please consider contributing them! See [CONTRIBUTING.md](https://github.com/enslo/sd-metadata/blob/main/CONTRIBUTING.md) for details.
|
|
67
70
|
|
|
68
71
|
## Format-Specific Behaviors
|
|
69
72
|
|
|
@@ -145,7 +148,7 @@ For userscripts (Tampermonkey, Violentmonkey, etc.), load the IIFE build via `@r
|
|
|
145
148
|
// ==UserScript==
|
|
146
149
|
// @name My Script
|
|
147
150
|
// @namespace https://example.com
|
|
148
|
-
// @require https://cdn.jsdelivr.net/npm/@enslo/sd-metadata@2.
|
|
151
|
+
// @require https://cdn.jsdelivr.net/npm/@enslo/sd-metadata@2.2.0/dist/index.global.js
|
|
149
152
|
// ==/UserScript==
|
|
150
153
|
|
|
151
154
|
const response = await fetch(imageUrl);
|
|
@@ -557,7 +560,8 @@ type GenerationSoftware =
|
|
|
557
560
|
| 'novelai' | 'comfyui' | 'swarmui' | 'tensorart' | 'stability-matrix'
|
|
558
561
|
| 'sd-webui' | 'forge' | 'forge-classic' | 'forge-neo'
|
|
559
562
|
| 'reforge'| 'easy-reforge' | 'sd-next' | 'civitai' | 'hf-space'
|
|
560
|
-
| 'invokeai' | 'easydiffusion' | 'fooocus' | 'ruined-fooocus'
|
|
563
|
+
| 'invokeai' | 'easydiffusion' | 'fooocus' | 'ruined-fooocus'
|
|
564
|
+
| 'draw-things';
|
|
561
565
|
```
|
|
562
566
|
|
|
563
567
|
### `EmbedMetadata`
|
|
@@ -586,25 +590,7 @@ For detailed documentation of all exported types including `ModelSettings`, `Sam
|
|
|
586
590
|
|
|
587
591
|
## Development
|
|
588
592
|
|
|
589
|
-
|
|
590
|
-
# Install dependencies
|
|
591
|
-
pnpm install
|
|
592
|
-
|
|
593
|
-
# Run tests
|
|
594
|
-
pnpm test
|
|
595
|
-
|
|
596
|
-
# Build
|
|
597
|
-
pnpm build
|
|
598
|
-
|
|
599
|
-
# Lint
|
|
600
|
-
pnpm lint
|
|
601
|
-
|
|
602
|
-
# Type check
|
|
603
|
-
pnpm typecheck
|
|
604
|
-
|
|
605
|
-
# Start demo site
|
|
606
|
-
pnpm demo
|
|
607
|
-
```
|
|
593
|
+
See the [Contributing Guide](https://github.com/enslo/sd-metadata/blob/main/CONTRIBUTING.md) for development setup and guidelines.
|
|
608
594
|
|
|
609
595
|
## License
|
|
610
596
|
|
package/dist/index.d.ts
CHANGED
|
@@ -44,6 +44,8 @@ type MetadataSegmentSource = {
|
|
|
44
44
|
prefix?: string;
|
|
45
45
|
} | {
|
|
46
46
|
type: 'jpegCom';
|
|
47
|
+
} | {
|
|
48
|
+
type: 'xmpPacket';
|
|
47
49
|
};
|
|
48
50
|
/**
|
|
49
51
|
* A single metadata segment with source tracking
|
|
@@ -70,7 +72,7 @@ type RawMetadata = {
|
|
|
70
72
|
/**
|
|
71
73
|
* Known AI image generation software
|
|
72
74
|
*/
|
|
73
|
-
type GenerationSoftware = 'novelai' | 'comfyui' | 'swarmui' | 'tensorart' | 'stability-matrix' | 'invokeai' | 'forge' | 'forge-classic' | 'forge-neo' | 'reforge' | 'easy-reforge' | 'sd-webui' | 'sd-next' | 'civitai' | 'hf-space' | 'easydiffusion' | 'fooocus' | 'ruined-fooocus';
|
|
75
|
+
type GenerationSoftware = 'novelai' | 'comfyui' | 'swarmui' | 'tensorart' | 'stability-matrix' | 'invokeai' | 'forge' | 'forge-classic' | 'forge-neo' | 'reforge' | 'easy-reforge' | 'sd-webui' | 'sd-next' | 'civitai' | 'hf-space' | 'easydiffusion' | 'fooocus' | 'ruined-fooocus' | 'draw-things';
|
|
74
76
|
/**
|
|
75
77
|
* Base metadata fields shared by all tools
|
|
76
78
|
*/
|
|
@@ -200,7 +202,7 @@ type ComfyUIMetadata = BasicComfyUIMetadata | SwarmUIMetadata;
|
|
|
200
202
|
* NovelAI's character prompts or ComfyUI's node graphs.
|
|
201
203
|
*/
|
|
202
204
|
interface StandardMetadata extends BaseMetadata {
|
|
203
|
-
software: 'sd-webui' | 'sd-next' | 'forge' | 'forge-classic' | 'forge-neo' | 'reforge' | 'easy-reforge' | 'invokeai' | 'civitai' | 'hf-space' | 'easydiffusion' | 'fooocus' | 'ruined-fooocus';
|
|
205
|
+
software: 'sd-webui' | 'sd-next' | 'forge' | 'forge-classic' | 'forge-neo' | 'reforge' | 'easy-reforge' | 'invokeai' | 'civitai' | 'hf-space' | 'easydiffusion' | 'fooocus' | 'ruined-fooocus' | 'draw-things';
|
|
204
206
|
}
|
|
205
207
|
/**
|
|
206
208
|
* Unified generation metadata (discriminated union)
|