@codexo/exojs-aseprite 0.14.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/LICENSE +21 -0
- package/dist/esm/AsepriteData.d.ts +86 -0
- package/dist/esm/AsepriteData.js +10 -0
- package/dist/esm/AsepriteData.js.map +1 -0
- package/dist/esm/AsepriteSheet.d.ts +61 -0
- package/dist/esm/AsepriteSheet.js +130 -0
- package/dist/esm/AsepriteSheet.js.map +1 -0
- package/dist/esm/asepriteBinding.d.ts +27 -0
- package/dist/esm/asepriteBinding.js +102 -0
- package/dist/esm/asepriteBinding.js.map +1 -0
- package/dist/esm/asepriteExtension.d.ts +13 -0
- package/dist/esm/asepriteExtension.js +22 -0
- package/dist/esm/asepriteExtension.js.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/public.d.ts +16 -0
- package/dist/esm/register.d.ts +1 -0
- package/dist/esm/register.js +15 -0
- package/dist/esm/register.js.map +1 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Codexo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/** Playback direction of an Aseprite frame tag animation. */
|
|
2
|
+
export type AsepriteDirection = 'forward' | 'pingpong' | 'pingpong_reverse' | 'reverse';
|
|
3
|
+
/** Pixel region rectangle used throughout the Aseprite JSON format. */
|
|
4
|
+
export interface AsepriteRect {
|
|
5
|
+
readonly h: number;
|
|
6
|
+
readonly w: number;
|
|
7
|
+
readonly x: number;
|
|
8
|
+
readonly y: number;
|
|
9
|
+
}
|
|
10
|
+
/** Width/height size descriptor used in Aseprite metadata. */
|
|
11
|
+
export interface AsepriteSize {
|
|
12
|
+
readonly h: number;
|
|
13
|
+
readonly w: number;
|
|
14
|
+
}
|
|
15
|
+
/** A single animation frame in the Aseprite JSON export. */
|
|
16
|
+
export interface AsepriteFrameData {
|
|
17
|
+
/** Display duration of this frame in milliseconds. */
|
|
18
|
+
readonly duration: number;
|
|
19
|
+
/** Pixel region of this frame within the packed sprite sheet texture. */
|
|
20
|
+
readonly frame: AsepriteRect;
|
|
21
|
+
readonly rotated: boolean;
|
|
22
|
+
readonly sourceSize: AsepriteSize;
|
|
23
|
+
readonly spriteSourceSize: AsepriteRect;
|
|
24
|
+
readonly trimmed: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A named animation range defined via Aseprite frame tags.
|
|
28
|
+
* `from` and `to` are inclusive zero-based frame indices.
|
|
29
|
+
*/
|
|
30
|
+
export interface AsepriteFrameTag {
|
|
31
|
+
readonly color?: string;
|
|
32
|
+
readonly direction: AsepriteDirection;
|
|
33
|
+
/** Inclusive end frame index. */
|
|
34
|
+
readonly to: number;
|
|
35
|
+
/** Inclusive start frame index. */
|
|
36
|
+
readonly from: number;
|
|
37
|
+
readonly name: string;
|
|
38
|
+
}
|
|
39
|
+
/** A single layer entry in the Aseprite JSON metadata. */
|
|
40
|
+
export interface AsepriteLayer {
|
|
41
|
+
readonly blendMode: string;
|
|
42
|
+
readonly name: string;
|
|
43
|
+
readonly opacity: number;
|
|
44
|
+
}
|
|
45
|
+
/** Bounds of a named slice at a specific frame. */
|
|
46
|
+
export interface AsepriteSliceKey {
|
|
47
|
+
readonly bounds: AsepriteRect;
|
|
48
|
+
readonly frame: number;
|
|
49
|
+
}
|
|
50
|
+
/** A named slice defined in the Aseprite editor. */
|
|
51
|
+
export interface AsepriteSlice {
|
|
52
|
+
readonly color?: string;
|
|
53
|
+
readonly keys: readonly AsepriteSliceKey[];
|
|
54
|
+
readonly name: string;
|
|
55
|
+
}
|
|
56
|
+
/** Metadata block of an Aseprite JSON export. */
|
|
57
|
+
export interface AsepriteMeta {
|
|
58
|
+
readonly app: string;
|
|
59
|
+
readonly format: string;
|
|
60
|
+
readonly frameTags?: readonly AsepriteFrameTag[];
|
|
61
|
+
/** Relative path to the exported sprite sheet image. */
|
|
62
|
+
readonly image: string;
|
|
63
|
+
readonly layers?: readonly AsepriteLayer[];
|
|
64
|
+
readonly scale: string;
|
|
65
|
+
readonly size: AsepriteSize;
|
|
66
|
+
readonly slices?: readonly AsepriteSlice[];
|
|
67
|
+
readonly version: string;
|
|
68
|
+
}
|
|
69
|
+
/** Aseprite JSON export in array mode — frames is an ordered array. */
|
|
70
|
+
export interface AsepriteArrayData {
|
|
71
|
+
readonly frames: readonly AsepriteFrameData[];
|
|
72
|
+
readonly meta: AsepriteMeta;
|
|
73
|
+
}
|
|
74
|
+
/** Aseprite JSON export in hash mode — frames is an object keyed by frame name. */
|
|
75
|
+
export interface AsepriteHashData {
|
|
76
|
+
readonly frames: Readonly<Record<string, AsepriteFrameData>>;
|
|
77
|
+
readonly meta: AsepriteMeta;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Union of both Aseprite JSON export formats.
|
|
81
|
+
*
|
|
82
|
+
* Use {@link isAsepriteArrayData} to discriminate between array and hash mode.
|
|
83
|
+
*/
|
|
84
|
+
export type AsepriteData = AsepriteArrayData | AsepriteHashData;
|
|
85
|
+
/** Returns `true` when `data` is in array mode (frames is an array). */
|
|
86
|
+
export declare function isAsepriteArrayData(data: AsepriteData): data is AsepriteArrayData;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// TypeScript types for the Aseprite JSON sprite sheet export format.
|
|
2
|
+
// Supports both array mode (frames is an ordered array) and hash mode
|
|
3
|
+
// (frames is an object keyed by frame name / filename).
|
|
4
|
+
/** Returns `true` when `data` is in array mode (frames is an array). */
|
|
5
|
+
function isAsepriteArrayData(data) {
|
|
6
|
+
return Array.isArray(data.frames);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export { isAsepriteArrayData };
|
|
10
|
+
//# sourceMappingURL=AsepriteData.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AsepriteData.js","sources":["../../../src/AsepriteData.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AACA;AAkGA;AACM,SAAU,mBAAmB,CAAC,IAAkB,EAAA;IACpD,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;AACnC;;;;"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { AnimatedSprite, type AnimatedSpriteClipDefinition, Spritesheet, type Texture } from '@codexo/exojs';
|
|
2
|
+
import { type AsepriteData } from './AsepriteData';
|
|
3
|
+
/**
|
|
4
|
+
* Parsed representation of an Aseprite JSON sprite sheet export.
|
|
5
|
+
*
|
|
6
|
+
* `AsepriteSheet.parse(data, texture)` converts the raw JSON document into:
|
|
7
|
+
* - A {@link Spritesheet} whose frames correspond to the Aseprite frame array
|
|
8
|
+
* (keyed by zero-based index string: `"0"`, `"1"`, …).
|
|
9
|
+
* - A `clips` map of {@link AnimatedSpriteClipDefinition} entries built from
|
|
10
|
+
* `meta.frameTags`, one per named tag.
|
|
11
|
+
*
|
|
12
|
+
* Call {@link createAnimatedSprite} to obtain a ready-to-use
|
|
13
|
+
* {@link AnimatedSprite} with all clips pre-registered.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const sheet = await loader.load(AsepriteSheet, 'hero.aseprite.json');
|
|
18
|
+
* const sprite = sheet.createAnimatedSprite();
|
|
19
|
+
* sprite.play('run');
|
|
20
|
+
* scene.addChild(sprite);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare class AsepriteSheet {
|
|
24
|
+
/** The underlying {@link Spritesheet} whose frames are keyed by index string. */
|
|
25
|
+
readonly spritesheet: Spritesheet;
|
|
26
|
+
/**
|
|
27
|
+
* Animation clips derived from the Aseprite `frameTags` metadata.
|
|
28
|
+
* Each clip's frames are live references into {@link spritesheet.frames};
|
|
29
|
+
* they are cloned automatically when passed to {@link AnimatedSprite.defineClip}.
|
|
30
|
+
*/
|
|
31
|
+
readonly clips: ReadonlyMap<string, AnimatedSpriteClipDefinition>;
|
|
32
|
+
/**
|
|
33
|
+
* @internal — use {@link AsepriteSheet.parse} to create instances.
|
|
34
|
+
* The public modifier is required for the Loader's `AssetConstructor` token
|
|
35
|
+
* contract; users should call `parse()` instead of constructing directly.
|
|
36
|
+
*/
|
|
37
|
+
constructor(spritesheet: Spritesheet, clips: ReadonlyMap<string, AnimatedSpriteClipDefinition>);
|
|
38
|
+
/**
|
|
39
|
+
* Parse a raw {@link AsepriteData} document and the already-loaded
|
|
40
|
+
* {@link Texture} into an {@link AsepriteSheet}.
|
|
41
|
+
*
|
|
42
|
+
* Supports both Aseprite array mode and hash mode. Frame indices from
|
|
43
|
+
* `frameTags` are resolved against the ordered frame array; out-of-range
|
|
44
|
+
* indices are silently skipped.
|
|
45
|
+
*
|
|
46
|
+
* Ping-pong directions (`pingpong`, `pingpong_reverse`) are recorded with
|
|
47
|
+
* `loop: true` but the reversed segment is not automatically appended —
|
|
48
|
+
* the clip plays only the declared `from`→`to` range.
|
|
49
|
+
*/
|
|
50
|
+
static parse(data: AsepriteData, texture: Texture): AsepriteSheet;
|
|
51
|
+
/**
|
|
52
|
+
* Create an {@link AnimatedSprite} with all frame-tag clips pre-defined.
|
|
53
|
+
*
|
|
54
|
+
* Each clip is registered via {@link AnimatedSprite.defineClip}, which
|
|
55
|
+
* clones the frame {@link Rectangle}s so the sprite owns its own copies.
|
|
56
|
+
* Call {@link AnimatedSprite.play} with a tag name to start playback.
|
|
57
|
+
*/
|
|
58
|
+
createAnimatedSprite(): AnimatedSprite;
|
|
59
|
+
/** Destroy the underlying {@link Spritesheet} and release its frame resources. */
|
|
60
|
+
destroy(): void;
|
|
61
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Spritesheet, AnimatedSprite } from '@codexo/exojs';
|
|
2
|
+
import { isAsepriteArrayData } from './AsepriteData.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Normalises an {@link AsepriteData} document into an ordered array of
|
|
6
|
+
* {@link AsepriteFrameData} entries regardless of whether the JSON was
|
|
7
|
+
* produced in array or hash mode.
|
|
8
|
+
*/
|
|
9
|
+
function normaliseFrames(data) {
|
|
10
|
+
if (isAsepriteArrayData(data)) {
|
|
11
|
+
return [...data.frames];
|
|
12
|
+
}
|
|
13
|
+
return Object.values(data.frames);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Calculates the average frames-per-second for a subset of frames, based on
|
|
17
|
+
* the per-frame `duration` field (milliseconds per frame) exported by Aseprite.
|
|
18
|
+
* Falls back to `12` fps when all durations are zero or the slice is empty.
|
|
19
|
+
*/
|
|
20
|
+
function avgFps(frames, from, to) {
|
|
21
|
+
const slice = frames.slice(from, to + 1);
|
|
22
|
+
if (slice.length === 0) {
|
|
23
|
+
return 12;
|
|
24
|
+
}
|
|
25
|
+
const totalMs = slice.reduce((sum, f) => sum + f.duration, 0);
|
|
26
|
+
const avgMs = totalMs / slice.length;
|
|
27
|
+
return avgMs > 0 ? 1000 / avgMs : 12;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Parsed representation of an Aseprite JSON sprite sheet export.
|
|
31
|
+
*
|
|
32
|
+
* `AsepriteSheet.parse(data, texture)` converts the raw JSON document into:
|
|
33
|
+
* - A {@link Spritesheet} whose frames correspond to the Aseprite frame array
|
|
34
|
+
* (keyed by zero-based index string: `"0"`, `"1"`, …).
|
|
35
|
+
* - A `clips` map of {@link AnimatedSpriteClipDefinition} entries built from
|
|
36
|
+
* `meta.frameTags`, one per named tag.
|
|
37
|
+
*
|
|
38
|
+
* Call {@link createAnimatedSprite} to obtain a ready-to-use
|
|
39
|
+
* {@link AnimatedSprite} with all clips pre-registered.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* const sheet = await loader.load(AsepriteSheet, 'hero.aseprite.json');
|
|
44
|
+
* const sprite = sheet.createAnimatedSprite();
|
|
45
|
+
* sprite.play('run');
|
|
46
|
+
* scene.addChild(sprite);
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
class AsepriteSheet {
|
|
50
|
+
/** The underlying {@link Spritesheet} whose frames are keyed by index string. */
|
|
51
|
+
spritesheet;
|
|
52
|
+
/**
|
|
53
|
+
* Animation clips derived from the Aseprite `frameTags` metadata.
|
|
54
|
+
* Each clip's frames are live references into {@link spritesheet.frames};
|
|
55
|
+
* they are cloned automatically when passed to {@link AnimatedSprite.defineClip}.
|
|
56
|
+
*/
|
|
57
|
+
clips;
|
|
58
|
+
/**
|
|
59
|
+
* @internal — use {@link AsepriteSheet.parse} to create instances.
|
|
60
|
+
* The public modifier is required for the Loader's `AssetConstructor` token
|
|
61
|
+
* contract; users should call `parse()` instead of constructing directly.
|
|
62
|
+
*/
|
|
63
|
+
constructor(spritesheet, clips) {
|
|
64
|
+
this.spritesheet = spritesheet;
|
|
65
|
+
this.clips = clips;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Parse a raw {@link AsepriteData} document and the already-loaded
|
|
69
|
+
* {@link Texture} into an {@link AsepriteSheet}.
|
|
70
|
+
*
|
|
71
|
+
* Supports both Aseprite array mode and hash mode. Frame indices from
|
|
72
|
+
* `frameTags` are resolved against the ordered frame array; out-of-range
|
|
73
|
+
* indices are silently skipped.
|
|
74
|
+
*
|
|
75
|
+
* Ping-pong directions (`pingpong`, `pingpong_reverse`) are recorded with
|
|
76
|
+
* `loop: true` but the reversed segment is not automatically appended —
|
|
77
|
+
* the clip plays only the declared `from`→`to` range.
|
|
78
|
+
*/
|
|
79
|
+
static parse(data, texture) {
|
|
80
|
+
const frameArray = normaliseFrames(data);
|
|
81
|
+
// Build SpritesheetData: frame names are zero-based index strings.
|
|
82
|
+
const spritesheetFrames = {};
|
|
83
|
+
for (let i = 0; i < frameArray.length; i++) {
|
|
84
|
+
const frameData = frameArray[i];
|
|
85
|
+
spritesheetFrames[String(i)] = { frame: frameData.frame };
|
|
86
|
+
}
|
|
87
|
+
const spritesheet = new Spritesheet(texture, { frames: spritesheetFrames });
|
|
88
|
+
// Build clips from frameTags, resolving frame indices into Rectangles.
|
|
89
|
+
const clips = new Map();
|
|
90
|
+
const frameTags = data.meta.frameTags ?? [];
|
|
91
|
+
for (const tag of frameTags) {
|
|
92
|
+
const frames = [];
|
|
93
|
+
for (let i = tag.from; i <= tag.to; i++) {
|
|
94
|
+
if (i >= 0 && i < frameArray.length) {
|
|
95
|
+
frames.push(spritesheet.getFrame(String(i)));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (frames.length === 0) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
clips.set(tag.name, {
|
|
102
|
+
fps: avgFps(frameArray, tag.from, tag.to),
|
|
103
|
+
frames,
|
|
104
|
+
loop: true,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return new AsepriteSheet(spritesheet, clips);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Create an {@link AnimatedSprite} with all frame-tag clips pre-defined.
|
|
111
|
+
*
|
|
112
|
+
* Each clip is registered via {@link AnimatedSprite.defineClip}, which
|
|
113
|
+
* clones the frame {@link Rectangle}s so the sprite owns its own copies.
|
|
114
|
+
* Call {@link AnimatedSprite.play} with a tag name to start playback.
|
|
115
|
+
*/
|
|
116
|
+
createAnimatedSprite() {
|
|
117
|
+
const sprite = new AnimatedSprite(this.spritesheet.texture);
|
|
118
|
+
for (const [name, clip] of this.clips) {
|
|
119
|
+
sprite.defineClip(name, clip);
|
|
120
|
+
}
|
|
121
|
+
return sprite;
|
|
122
|
+
}
|
|
123
|
+
/** Destroy the underlying {@link Spritesheet} and release its frame resources. */
|
|
124
|
+
destroy() {
|
|
125
|
+
this.spritesheet.destroy();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export { AsepriteSheet };
|
|
130
|
+
//# sourceMappingURL=AsepriteSheet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AsepriteSheet.js","sources":["../../../src/AsepriteSheet.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AsepriteSheet } from './AsepriteSheet';
|
|
2
|
+
/**
|
|
3
|
+
* Thrown when an Aseprite JSON document does not match the expected shape.
|
|
4
|
+
* `source` is the URL of the file being parsed.
|
|
5
|
+
*/
|
|
6
|
+
export declare class AsepriteFormatError extends Error {
|
|
7
|
+
readonly source: string;
|
|
8
|
+
constructor(source: string, message: string);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Declarative asset binding for {@link AsepriteSheet}.
|
|
12
|
+
*
|
|
13
|
+
* `loader.load(AsepriteSheet, 'hero.aseprite.json')` fetches and validates the
|
|
14
|
+
* Aseprite JSON export, resolves the packed image URL from `meta.image`
|
|
15
|
+
* (relative to the JSON source), loads the {@link Texture} via the Loader's
|
|
16
|
+
* sub-load deduplication, and constructs a fully-parsed {@link AsepriteSheet}.
|
|
17
|
+
*
|
|
18
|
+
* The `aseprite` type name enables the asset-config shorthand:
|
|
19
|
+
* `{ type: 'aseprite', source: 'hero.aseprite.json' }`.
|
|
20
|
+
*/
|
|
21
|
+
export declare const asepriteBinding: {
|
|
22
|
+
type: typeof AsepriteSheet;
|
|
23
|
+
typeNames: string[];
|
|
24
|
+
create(): {
|
|
25
|
+
load(req: import("@codexo/exojs").AssetLoadRequest<undefined>, ctx: import("@codexo/exojs").AssetLoaderContext): Promise<AsepriteSheet>;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Texture } from '@codexo/exojs';
|
|
2
|
+
import { AsepriteSheet } from './AsepriteSheet.js';
|
|
3
|
+
|
|
4
|
+
// Relative-path resolution for Aseprite image references (JSON → PNG).
|
|
5
|
+
// Mirrors the approach used in @codexo/exojs-tiled: Aseprite stores the image
|
|
6
|
+
// path relative to the JSON file; asset sources are often themselves relative,
|
|
7
|
+
// so plain `new URL(ref, base)` cannot be used when `base` has no scheme.
|
|
8
|
+
// ── URL resolution ───────────────────────────────────────────────────────────
|
|
9
|
+
/** Matches references that are already absolute: scheme, `//`, `/`, data/blob. */
|
|
10
|
+
const absoluteRefPattern = /^(?:[a-z][a-z\d+.-]*:|\/\/|\/)/i;
|
|
11
|
+
/** Matches a base that has an explicit scheme (absolute URL). */
|
|
12
|
+
const absoluteBasePattern = /^[a-z][a-z\d+.-]*:/i;
|
|
13
|
+
/** Synthetic origin used to borrow `URL`'s `../`/`./` collapsing. */
|
|
14
|
+
const syntheticOrigin = 'https://exojs.invalid/';
|
|
15
|
+
/**
|
|
16
|
+
* Resolves `ref` (the image path read from an Aseprite JSON file) relative to
|
|
17
|
+
* `base` (the resolved location of the JSON file itself).
|
|
18
|
+
*
|
|
19
|
+
* - Absolute refs (scheme, `//`, `/`, `data:`, `blob:`) are returned as-is.
|
|
20
|
+
* - Absolute bases delegate to `new URL(ref, base).href`.
|
|
21
|
+
* - Relative bases use a synthetic origin to collapse `./` and `../` segments,
|
|
22
|
+
* then strips the origin from the result.
|
|
23
|
+
*/
|
|
24
|
+
function resolveAsepriteUrl(ref, base) {
|
|
25
|
+
if (absoluteRefPattern.test(ref)) {
|
|
26
|
+
return ref;
|
|
27
|
+
}
|
|
28
|
+
if (absoluteBasePattern.test(base)) {
|
|
29
|
+
return new URL(ref, base).href;
|
|
30
|
+
}
|
|
31
|
+
const resolved = new URL(ref, syntheticOrigin + base.replace(/^\/+/, ''));
|
|
32
|
+
return resolved.href.slice(syntheticOrigin.length);
|
|
33
|
+
}
|
|
34
|
+
// ── Validation ───────────────────────────────────────────────────────────────
|
|
35
|
+
/**
|
|
36
|
+
* Thrown when an Aseprite JSON document does not match the expected shape.
|
|
37
|
+
* `source` is the URL of the file being parsed.
|
|
38
|
+
*/
|
|
39
|
+
class AsepriteFormatError extends Error {
|
|
40
|
+
source;
|
|
41
|
+
constructor(source, message) {
|
|
42
|
+
super(`[AsepriteFormatError] ${source}: ${message}`);
|
|
43
|
+
this.name = 'AsepriteFormatError';
|
|
44
|
+
this.source = source;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Validates an `unknown` value against the minimum required Aseprite JSON
|
|
49
|
+
* shape and narrows it to {@link AsepriteData}. Throws {@link AsepriteFormatError}
|
|
50
|
+
* on any mismatch.
|
|
51
|
+
*/
|
|
52
|
+
function validateAsepriteData(raw, source) {
|
|
53
|
+
if (typeof raw !== 'object' || raw === null) {
|
|
54
|
+
throw new AsepriteFormatError(source, 'root must be an object');
|
|
55
|
+
}
|
|
56
|
+
const doc = raw;
|
|
57
|
+
if (!('frames' in doc)) {
|
|
58
|
+
throw new AsepriteFormatError(source, 'missing required field "frames"');
|
|
59
|
+
}
|
|
60
|
+
if (!('meta' in doc) || typeof doc.meta !== 'object' || doc.meta === null) {
|
|
61
|
+
throw new AsepriteFormatError(source, 'missing required field "meta"');
|
|
62
|
+
}
|
|
63
|
+
const meta = doc.meta;
|
|
64
|
+
if (typeof meta.image !== 'string' || meta.image.length === 0) {
|
|
65
|
+
throw new AsepriteFormatError(source, '"meta.image" must be a non-empty string');
|
|
66
|
+
}
|
|
67
|
+
const frames = doc.frames;
|
|
68
|
+
if (!Array.isArray(frames) && (typeof frames !== 'object' || frames === null)) {
|
|
69
|
+
throw new AsepriteFormatError(source, '"frames" must be an array or an object');
|
|
70
|
+
}
|
|
71
|
+
return doc;
|
|
72
|
+
}
|
|
73
|
+
// ── Asset binding ─────────────────────────────────────────────────────────────
|
|
74
|
+
/**
|
|
75
|
+
* Declarative asset binding for {@link AsepriteSheet}.
|
|
76
|
+
*
|
|
77
|
+
* `loader.load(AsepriteSheet, 'hero.aseprite.json')` fetches and validates the
|
|
78
|
+
* Aseprite JSON export, resolves the packed image URL from `meta.image`
|
|
79
|
+
* (relative to the JSON source), loads the {@link Texture} via the Loader's
|
|
80
|
+
* sub-load deduplication, and constructs a fully-parsed {@link AsepriteSheet}.
|
|
81
|
+
*
|
|
82
|
+
* The `aseprite` type name enables the asset-config shorthand:
|
|
83
|
+
* `{ type: 'aseprite', source: 'hero.aseprite.json' }`.
|
|
84
|
+
*/
|
|
85
|
+
const asepriteBinding = {
|
|
86
|
+
type: AsepriteSheet,
|
|
87
|
+
typeNames: ['asepriteSheet'],
|
|
88
|
+
create() {
|
|
89
|
+
return {
|
|
90
|
+
async load(req, ctx) {
|
|
91
|
+
const raw = await ctx.fetchJson(req.source);
|
|
92
|
+
const data = validateAsepriteData(raw, req.source);
|
|
93
|
+
const imageUrl = resolveAsepriteUrl(data.meta.image, req.source);
|
|
94
|
+
const texture = (await ctx.loader.load(Texture, imageUrl));
|
|
95
|
+
return AsepriteSheet.parse(data, texture);
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export { AsepriteFormatError, asepriteBinding };
|
|
102
|
+
//# sourceMappingURL=asepriteBinding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asepriteBinding.js","sources":["../../../src/asepriteBinding.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Extension } from '@codexo/exojs/extensions';
|
|
2
|
+
/**
|
|
3
|
+
* Default immutable Aseprite extension descriptor.
|
|
4
|
+
*
|
|
5
|
+
* Registers one asset binding:
|
|
6
|
+
* - {@link asepriteBinding} — `loader.load(AsepriteSheet, 'hero.aseprite.json')` →
|
|
7
|
+
* fetches the Aseprite JSON, resolves and loads the packed texture, and
|
|
8
|
+
* returns a fully-parsed {@link AsepriteSheet} with all frame-tag clips.
|
|
9
|
+
*
|
|
10
|
+
* Use with `ApplicationOptions.extensions` or call
|
|
11
|
+
* `import '@codexo/exojs-aseprite/register'` for global auto-registration.
|
|
12
|
+
*/
|
|
13
|
+
export declare const asepriteExtension: Extension;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { asepriteBinding } from './asepriteBinding.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default immutable Aseprite extension descriptor.
|
|
5
|
+
*
|
|
6
|
+
* Registers one asset binding:
|
|
7
|
+
* - {@link asepriteBinding} — `loader.load(AsepriteSheet, 'hero.aseprite.json')` →
|
|
8
|
+
* fetches the Aseprite JSON, resolves and loads the packed texture, and
|
|
9
|
+
* returns a fully-parsed {@link AsepriteSheet} with all frame-tag clips.
|
|
10
|
+
*
|
|
11
|
+
* Use with `ApplicationOptions.extensions` or call
|
|
12
|
+
* `import '@codexo/exojs-aseprite/register'` for global auto-registration.
|
|
13
|
+
*/
|
|
14
|
+
const asepriteExtension = Object.freeze({
|
|
15
|
+
id: '@codexo/exojs-aseprite',
|
|
16
|
+
// Localized erasure cast: typed binding (Options=undefined) meets the
|
|
17
|
+
// untyped Extension.assets contract here. Runtime behavior is unaffected.
|
|
18
|
+
assets: [asepriteBinding],
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export { asepriteExtension };
|
|
22
|
+
//# sourceMappingURL=asepriteExtension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asepriteExtension.js","sources":["../../../src/asepriteExtension.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAIA;;;;;;;;;;AAUG;AACI,MAAM,iBAAiB,GAAc,MAAM,CAAC,MAAM,CAAC;AACxD,IAAA,EAAE,EAAE,wBAAwB;;;IAG5B,MAAM,EAAE,CAAC,eAAe,CAA8B;AACvD,CAAA;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './public';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { AsepriteFormatError, asepriteBinding } from './asepriteBinding.js';
|
|
2
|
+
export { isAsepriteArrayData } from './AsepriteData.js';
|
|
3
|
+
export { asepriteExtension } from './asepriteExtension.js';
|
|
4
|
+
export { AsepriteSheet } from './AsepriteSheet.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { asepriteBinding, AsepriteFormatError } from './asepriteBinding';
|
|
2
|
+
export type { AsepriteArrayData, AsepriteData, AsepriteDirection, AsepriteFrameData, AsepriteFrameTag, AsepriteHashData, AsepriteLayer, AsepriteMeta, AsepriteRect, AsepriteSize, AsepriteSlice, AsepriteSliceKey, } from './AsepriteData';
|
|
3
|
+
export { isAsepriteArrayData } from './AsepriteData';
|
|
4
|
+
export { asepriteExtension } from './asepriteExtension';
|
|
5
|
+
export { AsepriteSheet } from './AsepriteSheet';
|
|
6
|
+
import type { AsepriteSheet } from './AsepriteSheet';
|
|
7
|
+
declare module '@codexo/exojs' {
|
|
8
|
+
interface AssetDefinitions {
|
|
9
|
+
asepriteSheet: {
|
|
10
|
+
resource: AsepriteSheet;
|
|
11
|
+
config: {
|
|
12
|
+
source: string;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './public';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ExtensionRegistry } from '@codexo/exojs/extensions';
|
|
2
|
+
import { asepriteExtension } from './asepriteExtension.js';
|
|
3
|
+
export { AsepriteFormatError, asepriteBinding } from './asepriteBinding.js';
|
|
4
|
+
export { isAsepriteArrayData } from './AsepriteData.js';
|
|
5
|
+
export { AsepriteSheet } from './AsepriteSheet.js';
|
|
6
|
+
|
|
7
|
+
// @codexo/exojs-aseprite/register — explicit registration entry.
|
|
8
|
+
// Importing this entry registers the default asepriteExtension descriptor
|
|
9
|
+
// in the global ExtensionRegistry. Subsequently constructed Applications
|
|
10
|
+
// that use global defaults will receive the Aseprite extension.
|
|
11
|
+
// This is the only side-effectful entry in this package.
|
|
12
|
+
ExtensionRegistry.register(asepriteExtension);
|
|
13
|
+
|
|
14
|
+
export { asepriteExtension };
|
|
15
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sources":["../../../src/register.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AAMA,iBAAiB,CAAC,QAAQ,CAAC,iBAAiB,CAAC;;;;"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codexo/exojs-aseprite",
|
|
3
|
+
"version": "0.14.0",
|
|
4
|
+
"description": "Aseprite sprite sheet asset extension for ExoJS.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/Exoridus/ExoJS.git",
|
|
8
|
+
"directory": "packages/exojs-aseprite"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"sideEffects": [
|
|
12
|
+
"./dist/esm/register.js"
|
|
13
|
+
],
|
|
14
|
+
"main": "./dist/esm/index.js",
|
|
15
|
+
"module": "./dist/esm/index.js",
|
|
16
|
+
"types": "./dist/esm/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/esm/index.d.ts",
|
|
20
|
+
"import": "./dist/esm/index.js",
|
|
21
|
+
"default": "./dist/esm/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./register": {
|
|
24
|
+
"types": "./dist/esm/register.d.ts",
|
|
25
|
+
"import": "./dist/esm/register.js",
|
|
26
|
+
"default": "./dist/esm/register.js"
|
|
27
|
+
},
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist/esm/",
|
|
32
|
+
"README.md",
|
|
33
|
+
"LICENSE"
|
|
34
|
+
],
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@codexo/exojs": "0.14.x"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@codexo/exojs": "0.14.0",
|
|
40
|
+
"@codexo/exojs-config": "0.0.0"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsx ../../node_modules/rollup/dist/bin/rollup -c --environment EXOJS_ENV:production",
|
|
48
|
+
"build:dev": "tsx ../../node_modules/rollup/dist/bin/rollup -c --environment EXOJS_ENV:development",
|
|
49
|
+
"typecheck": "tsc --noEmit",
|
|
50
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
51
|
+
"test": "vitest run --root ../.. --project=exojs-aseprite"
|
|
52
|
+
}
|
|
53
|
+
}
|