@enslo/sd-metadata 1.2.0 โ†’ 1.3.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/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
  [![npm downloads](https://img.shields.io/npm/dm/@enslo/sd-metadata.svg)](https://www.npmjs.com/package/@enslo/sd-metadata)
5
5
  [![license](https://img.shields.io/npm/l/@enslo/sd-metadata.svg)](https://github.com/enslo/sd-metadata/blob/main/LICENSE)
6
6
 
7
+ ๐Ÿ‡ฏ๐Ÿ‡ต **[ๆ—ฅๆœฌ่ชž็‰ˆใฏใ“ใกใ‚‰](./README.ja.md)**
8
+
7
9
  A TypeScript library to read and write metadata embedded in AI-generated images.
8
10
 
9
11
  ## Features
@@ -88,7 +90,7 @@ const { read } = require('@enslo/sd-metadata');
88
90
  ### Node.js Usage
89
91
 
90
92
  ```typescript
91
- import { read, write } from 'sd-metadata';
93
+ import { read, write } from '@enslo/sd-metadata';
92
94
  import { readFileSync, writeFileSync } from 'fs';
93
95
 
94
96
  // Read metadata from any supported format
@@ -106,7 +108,7 @@ if (result.status === 'success') {
106
108
  ### Browser Usage
107
109
 
108
110
  ```typescript
109
- import { read } from 'sd-metadata';
111
+ import { read } from '@enslo/sd-metadata';
110
112
 
111
113
  // Handle file input
112
114
  const fileInput = document.querySelector('input[type="file"]');
@@ -151,15 +153,18 @@ if (result.status === 'success') {
151
153
  > For production use, pin to a specific version instead of `@latest`:
152
154
  >
153
155
  > ```text
154
- > https://cdn.jsdelivr.net/npm/@enslo/sd-metadata@1.2.0/dist/index.js
156
+ > https://cdn.jsdelivr.net/npm/@enslo/sd-metadata@1.3.0/dist/index.js
155
157
  > ```
156
158
 
157
- ### Format Conversion
159
+ ### Advanced Examples
160
+
161
+ <details>
162
+ <summary>Format Conversion</summary>
158
163
 
159
164
  Convert metadata between different image formats:
160
165
 
161
166
  ```typescript
162
- import { read, write } from 'sd-metadata';
167
+ import { read, write } from '@enslo/sd-metadata';
163
168
 
164
169
  // Read metadata from PNG
165
170
  const pngData = readFileSync('comfyui-output.png');
@@ -182,10 +187,13 @@ if (parseResult.status === 'success') {
182
187
  > [!TIP]
183
188
  > This library handles metadata read/write only. For actual image format conversion (decoding/encoding pixels), use image processing libraries like [sharp](https://www.npmjs.com/package/sharp), [jimp](https://www.npmjs.com/package/jimp), or browser Canvas API.
184
189
 
185
- ### Handling Different Result Types
190
+ </details>
191
+
192
+ <details>
193
+ <summary>Handling Different Result Types</summary>
186
194
 
187
195
  ```typescript
188
- import { read } from 'sd-metadata';
196
+ import { read } from '@enslo/sd-metadata';
189
197
 
190
198
  const result = read(imageData);
191
199
 
@@ -215,31 +223,37 @@ switch (result.status) {
215
223
  }
216
224
  ```
217
225
 
218
- ### Force Conversion for Unrecognized Formats
226
+ </details>
219
227
 
220
- When you have unrecognized metadata but still want to convert it:
228
+ <details>
229
+ <summary>Preserving Unrecognized Metadata</summary>
230
+
231
+ When converting images with metadata from unsupported tools, you can still preserve the original metadata:
221
232
 
222
233
  ```typescript
223
- import { read, write } from 'sd-metadata';
234
+ import { read, write } from '@enslo/sd-metadata';
224
235
 
225
236
  const source = read(unknownImage);
226
237
  // source.status === 'unrecognized'
227
238
 
228
- // Force blind conversion (preserves all metadata chunks/segments)
239
+ // Preserve all original metadata chunks/segments
229
240
  const result = write(targetImage, source, { force: true });
230
241
 
231
242
  if (result.ok) {
232
- // Metadata successfully converted even though format wasn't recognized
233
- console.log('Forced conversion succeeded');
243
+ // Original metadata preserved in the new image
244
+ console.log('Metadata preserved successfully');
234
245
  }
235
246
  ```
236
247
 
237
- ### Removing Metadata
248
+ </details>
249
+
250
+ <details>
251
+ <summary>Removing Metadata</summary>
238
252
 
239
253
  To strip all metadata from an image:
240
254
 
241
255
  ```typescript
242
- import { write } from 'sd-metadata';
256
+ import { write } from '@enslo/sd-metadata';
243
257
 
244
258
  const result = write(imageData, { status: 'empty' });
245
259
  if (result.ok) {
@@ -247,12 +261,15 @@ if (result.ok) {
247
261
  }
248
262
  ```
249
263
 
250
- ### Writing Metadata in WebUI Format
264
+ </details>
265
+
266
+ <details>
267
+ <summary>Writing Metadata in WebUI Format</summary>
251
268
 
252
269
  Create and embed custom metadata in SD WebUI (A1111) format:
253
270
 
254
271
  ```typescript
255
- import { writeAsWebUI } from 'sd-metadata';
272
+ import { writeAsWebUI } from '@enslo/sd-metadata';
256
273
 
257
274
  // Create custom metadata from scratch
258
275
  const metadata = {
@@ -284,20 +301,23 @@ if (result.ok) {
284
301
  > - Converting metadata from proprietary formats to WebUI-compatible format
285
302
  > - Building tools that need to output WebUI-readable metadata
286
303
 
287
- ### Formatting Metadata for Display
304
+ </details>
305
+
306
+ <details>
307
+ <summary>Formatting Metadata for Display</summary>
288
308
 
289
- Convert metadata to human-readable text in WebUI format:
309
+ Convert metadata from **any supported tool** to a unified, human-readable WebUI format. This normalizes the differences between tools (NovelAI, ComfyUI, Forge, etc.) into a consistent text format:
290
310
 
291
311
  ```typescript
292
- import { read, formatAsWebUI } from 'sd-metadata';
312
+ import { read, formatAsWebUI } from '@enslo/sd-metadata';
293
313
 
294
314
  const result = read(imageData);
295
315
  if (result.status === 'success') {
296
- // Convert to WebUI format text
316
+ // Works with any tool: NovelAI, ComfyUI, Forge, InvokeAI, etc.
297
317
  const text = formatAsWebUI(result.metadata);
298
318
  console.log(text);
299
319
 
300
- // Output example:
320
+ // Always outputs in consistent WebUI format:
301
321
  // masterpiece, best quality, 1girl
302
322
  // Negative prompt: lowres, bad quality
303
323
  // Steps: 20, Sampler: Euler a, CFG scale: 7, Seed: 12345, Size: 512x768, Model: model.safetensors
@@ -305,7 +325,9 @@ if (result.status === 'success') {
305
325
  ```
306
326
 
307
327
  > [!NOTE]
308
- > `formatAsWebUI` provides a tool-agnostic standard format for displaying generation metadata. It works with metadata from any supported tool (NovelAI, ComfyUI, etc.) and formats it consistently.
328
+ > Regardless of which tool generated the image, `formatAsWebUI` extracts the common generation parameters and formats them in a standardized way. This is ideal for displaying metadata to users without worrying about tool-specific formats.
329
+
330
+ </details>
309
331
 
310
332
  ## API Reference
311
333
 
@@ -335,13 +357,15 @@ Writes metadata to an image file.
335
357
  - `status: 'success'` or `'empty'` - Can write directly
336
358
  - `status: 'unrecognized'` - Requires `force: true` option
337
359
  - `options` - Optional settings:
338
- - `force?: boolean` - Required when writing `status: 'unrecognized'` metadata (blind conversion)
360
+ - `force?: boolean` - Enables writing unrecognized metadata (preserves original data as-is)
339
361
 
340
362
  **Returns:**
341
363
 
342
364
  - `{ ok: true, value: Uint8Array }` - Successfully written (returns new image data)
343
- - `{ ok: false, error: { type: string, message?: string } }` - Failed
344
- - `type`: `'unsupportedFormat'`, `'conversionFailed'`, or `'writeFailed'`
365
+ - `{ ok: false, error: { type, message? } }` - Failed. `type` is one of:
366
+ - `'unsupportedFormat'`: Target image is not PNG, JPEG, or WebP
367
+ - `'conversionFailed'`: Metadata conversion failed (e.g., incompatible format)
368
+ - `'writeFailed'`: Failed to embed metadata into the image
345
369
 
346
370
  ### `writeAsWebUI(data: Uint8Array, metadata: GenerationMetadata): WriteResult`
347
371
 
@@ -357,8 +381,9 @@ Writes metadata to an image in SD WebUI (A1111) format.
357
381
  **Returns:**
358
382
 
359
383
  - `{ ok: true, value: Uint8Array }` - Successfully written (returns new image data)
360
- - `{ ok: false, error: { type: string, message?: string } }` - Failed
361
- - `type`: `'unsupportedFormat'` or `'writeFailed'`
384
+ - `{ ok: false, error: { type, message? } }` - Failed. `type` is one of:
385
+ - `'unsupportedFormat'`: Target image is not PNG, JPEG, or WebP
386
+ - `'writeFailed'`: Failed to embed metadata into the image
362
387
 
363
388
  **Use cases:**
364
389
 
@@ -393,6 +418,41 @@ Steps: 20, Sampler: Euler a, CFG scale: 7, Seed: 12345, Size: 512x768, ...
393
418
  - Copying generation parameters as text
394
419
  - Logging or debugging generation settings
395
420
 
421
+ ### `formatRaw(raw: RawMetadata): string`
422
+
423
+ Formats raw metadata as plain text.
424
+
425
+ **Parameters:**
426
+
427
+ - `raw` - Raw metadata from `ParseResult` (`result.raw`)
428
+
429
+ **Returns:**
430
+
431
+ - Plain text content from the metadata (multiple entries separated by blank lines)
432
+
433
+ **Use cases:**
434
+
435
+ - Displaying unrecognized metadata to users
436
+ - Quick inspection of raw metadata content
437
+ - Fallback display when parsing fails
438
+
439
+ **Example:**
440
+
441
+ ```typescript
442
+ import { read, formatAsWebUI, formatRaw } from '@enslo/sd-metadata';
443
+
444
+ const result = read(imageData);
445
+
446
+ switch (result.status) {
447
+ case 'success':
448
+ console.log(formatAsWebUI(result.metadata));
449
+ break;
450
+ case 'unrecognized':
451
+ console.log(formatRaw(result.raw));
452
+ break;
453
+ }
454
+ ```
455
+
396
456
  ## Type Reference
397
457
 
398
458
  This section provides an overview of the main types. For complete type definitions, see [Type Documentation](./docs/types.md).
@@ -511,7 +571,7 @@ type RawMetadata =
511
571
  >
512
572
  > Use your IDE's IntelliSense for auto-completion and inline documentation.
513
573
 
514
- For detailed documentation of all exported types including `BaseMetadata`, `ModelSettings`, `SamplingSettings`, and format-specific types, see the [Type Documentation](./docs/types.md).
574
+ For detailed documentation of all exported types including `ModelSettings`, `SamplingSettings`, and format-specific types, see the [Type Documentation](./docs/types.md).
515
575
 
516
576
  ## Development
517
577
 
package/dist/index.d.ts CHANGED
@@ -397,7 +397,7 @@ declare function write(data: Uint8Array, metadata: ParseResult, options?: WriteO
397
397
  *
398
398
  * @example
399
399
  * ```typescript
400
- * import { writeAsWebUI } from 'sd-metadata';
400
+ * import { writeAsWebUI } from '@enslo/sd-metadata';
401
401
  *
402
402
  * // Create custom metadata
403
403
  * const metadata = {
@@ -445,7 +445,7 @@ declare function writeAsWebUI(data: Uint8Array, metadata: GenerationMetadata): W
445
445
  *
446
446
  * @example
447
447
  * ```typescript
448
- * import { read, formatAsWebUI } from 'sd-metadata';
448
+ * import { read, formatAsWebUI } from '@enslo/sd-metadata';
449
449
  *
450
450
  * const result = read(imageData);
451
451
  * if (result.status === 'success') {
@@ -460,4 +460,35 @@ declare function writeAsWebUI(data: Uint8Array, metadata: GenerationMetadata): W
460
460
  */
461
461
  declare function formatAsWebUI(metadata: GenerationMetadata): string;
462
462
 
463
- export { type CharacterPrompt, type GenerationMetadata, type HiresSettings, type ITXtChunk, type MetadataSegment, type MetadataSegmentSource, type ModelSettings, type ParseResult, type PngTextChunk, type RawMetadata, type SamplingSettings, type TExtChunk, type UpscaleSettings, type WriteOptions, type WriteResult, formatAsWebUI, read, write, writeAsWebUI };
463
+ /**
464
+ * Raw metadata serialization utilities
465
+ *
466
+ * Formats RawMetadata as human-readable plain text.
467
+ */
468
+
469
+ /**
470
+ * Format raw metadata as plain text
471
+ *
472
+ * Extracts text content from RawMetadata and returns it as a simple string.
473
+ * Multiple entries are separated by double newlines.
474
+ *
475
+ * This is useful for displaying unrecognized metadata to end users
476
+ * without needing to manually iterate over chunks or segments.
477
+ *
478
+ * @param raw - Raw metadata from ParseResult
479
+ * @returns Plain text content from the metadata
480
+ *
481
+ * @example
482
+ * ```typescript
483
+ * import { read, formatRaw } from '@enslo/sd-metadata';
484
+ *
485
+ * const result = read(imageData);
486
+ * if (result.status === 'unrecognized') {
487
+ * console.log(formatRaw(result.raw));
488
+ * // Output: the raw text content without prefixes
489
+ * }
490
+ * ```
491
+ */
492
+ declare function formatRaw(raw: RawMetadata): string;
493
+
494
+ export { type CharacterPrompt, type GenerationMetadata, type HiresSettings, type ITXtChunk, type MetadataSegment, type MetadataSegmentSource, type ModelSettings, type ParseResult, type PngTextChunk, type RawMetadata, type SamplingSettings, type TExtChunk, type UpscaleSettings, type WriteOptions, type WriteResult, formatAsWebUI, formatRaw, read, write, writeAsWebUI };
package/dist/index.js CHANGED
@@ -3012,8 +3012,20 @@ function createExifSegments(text) {
3012
3012
  }
3013
3013
  ];
3014
3014
  }
3015
+
3016
+ // src/serializers/raw.ts
3017
+ function formatRaw(raw) {
3018
+ switch (raw.format) {
3019
+ case "png":
3020
+ return raw.chunks.map((chunk) => chunk.text).join("\n\n");
3021
+ case "jpeg":
3022
+ case "webp":
3023
+ return raw.segments.map((segment) => segment.data).join("\n\n");
3024
+ }
3025
+ }
3015
3026
  export {
3016
3027
  formatAsWebUI,
3028
+ formatRaw,
3017
3029
  read,
3018
3030
  write,
3019
3031
  writeAsWebUI