@natsuneko-laboratory/memora 0.1.0 → 0.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
@@ -47,7 +47,7 @@ if (metadata) {
47
47
  function parseImageMetadata(input: ArrayBuffer | Uint8Array): Promise<ImageMetadata | null>;
48
48
  ```
49
49
 
50
- 画像から 1 件のメタデータを取得します。複数形式が同居する場合は ResoniteScreenshotExtensions を優先し、それ以外は解析結果の先頭を返します。
50
+ 画像から 1 件のメタデータを取得します。複数形式が同居する場合は VRChat、VRCX、ResoniteScreenshotExtensions の順で優先します。
51
51
 
52
52
  `parsePhotoMetadata` はこの関数の別名です。
53
53
 
@@ -163,6 +163,8 @@ async function readScreenshot(uri: string, readBytes: (uri: string) => Promise<U
163
163
 
164
164
  `readBytes` には、アプリで採用しているファイルアクセスライブラリを使った読み取り関数を渡してください。URI、Base64、`File`、`Blob` をパーサーへ直接渡すことはできません。
165
165
 
166
+ Metro は `react-native` 条件(従来の解決方式では同名のフィールド)から専用バンドルを読み込みます。Node.js モジュールのポリフィルや Metro の追加設定は不要です。
167
+
166
168
  ## 対応範囲と制約
167
169
 
168
170
  PNG の iTXt(非圧縮・zlib 圧縮)と XMP を読み取ります。ResoniteScreenshotExtensions の JPEG XMP にも対応します。
@@ -171,6 +173,10 @@ PNG の iTXt(非圧縮・zlib 圧縮)と XMP を読み取ります。Resonit
171
173
 
172
174
  コアは React やネイティブモジュールに依存しません。Node.js の `Buffer` / `process`、DOM、`TextDecoder` がない環境でのバンドルテストを用意しています。
173
175
 
176
+ React Native 向けには、依存先 `exifr` の Node.js 専用ローダーを除いたバンドルを生成します。v0.1.0 では、このローダーの動的 `import` が Metro の依存解析エラーを起こしていました。Metro によるパッケージ解決・バンドルと、ホスト API のない環境での PNG・JPEG 解析を回帰テストで検証しています。iOS / Android 実機でのテストではありません。
177
+
178
+ `navigator` が存在しても `userAgent` がない React Native 環境に対応するため、専用バンドルでは exifr のブラウザー描画補正用 UA 参照を空文字に置き換えます。アプリ側で `navigator.userAgent` を補完する必要はなく、グローバル変数も変更しません。
179
+
174
180
  ## 開発
175
181
 
176
182
  リポジトリを取得した後、パッケージのディレクトリで実行します。
@@ -186,7 +192,7 @@ npm run build
186
192
 
187
193
  `npm run typecheck` は本体とテストの両方を検証します。テストのみの型チェックには `npm run typecheck:test` を使用できます。
188
194
 
189
- ビルドすると、ESM と型定義が `dist/` に生成されます。インストール時のスクリプトを無効にしている場合は、利用前に `npm run build` を実行してください。
195
+ ビルドすると、ESM、React Native 向けバンドル、型定義が `dist/` に生成されます。インストール時のスクリプトを無効にしている場合は、利用前に `npm run build` を実行してください。
190
196
 
191
197
  ## ライセンス
192
198
 
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { ImageMetadata, PhotoInput } from "./types.js";
2
2
  export type * from "./types.js";
3
3
  /** Read every recognized packet without dropping coexisting formats. Unknown formats return an empty array. */
4
4
  export declare const parseAllImageMetadata: (input: PhotoInput) => Promise<ImageMetadata[]>;
5
- /** Resonite takes precedence, matching steambird; use parseAllImageMetadata for mixed images. */
5
+ /** Prefer VRChat, then VRCX, then ResoniteScreenshotExtensions for mixed images. */
6
6
  export declare const parseImageMetadata: (input: PhotoInput) => Promise<ImageMetadata | null>;
7
7
  /** Alias for existing callers. */
8
8
  export declare const parsePhotoMetadata: typeof parseImageMetadata;
package/dist/index.js CHANGED
@@ -213,12 +213,23 @@ export const parseAllImageMetadata = async (input) => {
213
213
  }));
214
214
  }
215
215
  }
216
- return result;
216
+ const priority = {
217
+ VRChat: 0,
218
+ VRCX: 1,
219
+ ResoniteScreenshotExtensions: 2,
220
+ };
221
+ // A screenshot can contain metadata written by more than one application.
222
+ // Keep duplicate records and their relative order, but expose the supported
223
+ // format precedence consistently to callers.
224
+ return result
225
+ .map((metadata, index) => ({ metadata, index }))
226
+ .sort((a, b) => priority[a.metadata.type] - priority[b.metadata.type] || a.index - b.index)
227
+ .map(({ metadata }) => metadata);
217
228
  };
218
- /** Resonite takes precedence, matching steambird; use parseAllImageMetadata for mixed images. */
229
+ /** Prefer VRChat, then VRCX, then ResoniteScreenshotExtensions for mixed images. */
219
230
  export const parseImageMetadata = async (input) => {
220
231
  const results = await parseAllImageMetadata(input);
221
- return (results.find((result) => result.type === "ResoniteScreenshotExtensions") ?? results[0] ?? null);
232
+ return results[0] ?? null;
222
233
  };
223
234
  /** Alias for existing callers. */
224
235
  export const parsePhotoMetadata = parseImageMetadata;