From afe76719ed77e6aa971dbe843e9edb0f17809d10 Mon Sep 17 00:00:00 2001 From: Zyie <24736175+Zyie@users.noreply.github.com> Date: Tue, 25 Jun 2024 09:53:53 +0100 Subject: [PATCH 1/3] feat: add global `copy` tag (#33) --- src/core/pipes/PipeSystem.ts | 10 + src/webfont/sdf.ts | 5 +- test/core/Assetpack.test.ts | 42 ++++ test/manifest/Manifest.test.ts | 418 ++++++++++++++++++--------------- 4 files changed, 286 insertions(+), 189 deletions(-) diff --git a/src/core/pipes/PipeSystem.ts b/src/core/pipes/PipeSystem.ts index 2e8e55f..3939317 100644 --- a/src/core/pipes/PipeSystem.ts +++ b/src/core/pipes/PipeSystem.ts @@ -1,3 +1,4 @@ +import { finalCopyPipe } from './finalCopyPipe.js'; import { mergePipeOptions } from './mergePipeOptions.js'; import { multiPipe } from './multiPipe.js'; @@ -72,6 +73,15 @@ export class PipeSystem pipeIndex++; + // if the asset has the copy tag on it, then the only pipe that should be run is the final copy pipe + // this is to ensure that the asset is copied to the output directory without any other processing + if (asset.allMetaData.copy && pipe !== finalCopyPipe) + { + await this._transform(asset, pipeIndex); + + return; + } + const options = mergePipeOptions(pipe, asset); if (options !== false && pipe.transform && pipe.test?.(asset, options)) diff --git a/src/webfont/sdf.ts b/src/webfont/sdf.ts index c6d561e..cbe8527 100644 --- a/src/webfont/sdf.ts +++ b/src/webfont/sdf.ts @@ -12,7 +12,7 @@ export interface SDFFontOptions extends PluginOptions<'font' | 'nc' | 'fix'> font?: Omit; } -export function signedFont( +function signedFont( defaultOptions: SDFFontOptions ): AssetPipe { @@ -45,8 +45,7 @@ export function signedFont( const newTextureAsset = createNewAssetAt(asset, newTextureName); // don't compress! - newTextureAsset.metaData[options.tags.nc] = true; - newTextureAsset.metaData[options.tags.fix] = true; + newTextureAsset.metaData.copy = true; assets.push(newTextureAsset); diff --git a/test/core/Assetpack.test.ts b/test/core/Assetpack.test.ts index e54e18c..30c9bde 100644 --- a/test/core/Assetpack.test.ts +++ b/test/core/Assetpack.test.ts @@ -241,6 +241,48 @@ describe('Core', () => expect(existsSync(join(outputDir, 'scripts/test.json'))).toBe(false); }); + it('should copy assets when copy tag is used', async () => + { + const testName = 'copy-tag'; + const inputDir = getInputDir(pkg, testName); + const outputDir = getOutputDir(pkg, testName); + + createFolder( + pkg, + { + name: testName, + files: [], + folders: [{ + name: 'scripts{copy}', + files: [{ + name: 'json.json', + content: assetPath('json/json.json'), + }], + folders: [], + }, + { + name: 'scripts2', + files: [{ + name: 'json{copy}.json', + content: assetPath('json/json.json'), + }], + folders: [], + }], + }); + + const assetpack = new AssetPack({ + entry: inputDir, + output: outputDir, + cache: false, + ignore: ['**/scripts/**/*'], + }); + + await assetpack.run(); + + expect(existsSync(join(outputDir, 'scripts/json.json'))).toBe(true); + expect(existsSync(join(outputDir, 'scripts2/json.json'))).toBe(true); + }); + it('should provide the correct options overrides to the plugin', async () => { const testName = 'plugin-options-override'; diff --git a/test/manifest/Manifest.test.ts b/test/manifest/Manifest.test.ts index 0c6b8aa..96dfbbf 100644 --- a/test/manifest/Manifest.test.ts +++ b/test/manifest/Manifest.test.ts @@ -7,23 +7,17 @@ import { compress, mipmap } from '../../src/image/index.js'; import { pixiManifest } from '../../src/manifest/index.js'; import { spineAtlasManifestMod, spineAtlasMipmap } from '../../src/spine/index.js'; import { texturePacker, texturePackerManifestMod } from '../../src/texture-packer/index.js'; -import { - assetPath, - createFolder, - getCacheDir, - getInputDir, - getOutputDir -} from '../utils/index.js'; +import { assetPath, createFolder, getCacheDir, getInputDir, getOutputDir } from '../utils/index.js'; import type { File } from '../utils/index.js'; const pkg = 'manifest'; -function genSprites() +function genSprites(total = 10) { const sprites: File[] = []; - for (let i = 0; i < 10; i++) + for (let i = 0; i < total; i++) { sprites.push({ name: `sprite${i}.png`, @@ -116,7 +110,8 @@ describe('Manifest', () => } const assetpack = new AssetPack({ - entry: inputDir, cacheLocation: getCacheDir(pkg, testName), + entry: inputDir, + cacheLocation: getCacheDir(pkg, testName), output: outputDir, cache: useCache, pipes: [ @@ -137,13 +132,13 @@ describe('Manifest', () => pixiManifest(), spineAtlasManifestMod(), texturePackerManifestMod(), - ] + ], }); await assetpack.run(); // load the manifest json - const manifest = sortObjectProperties((await fs.readJSONSync(`${outputDir}/manifest.json`))) as any; + const manifest = sortObjectProperties(await fs.readJSONSync(`${outputDir}/manifest.json`)) as any; expect(manifest.bundles[1]).toEqual({ name: 'bundle', @@ -182,10 +177,7 @@ describe('Manifest', () => }, { alias: ['bundle/tps-0'], - src: [ - 'bundle/tps-0@0.5x.json', - 'bundle/tps-0.json', - ], + src: ['bundle/tps-0@0.5x.json', 'bundle/tps-0.json'], data: { tags: { tps: true, @@ -195,10 +187,7 @@ describe('Manifest', () => }, { alias: ['bundle/tps-1'], - src: [ - 'bundle/tps-1@0.5x.json', - 'bundle/tps-1.json', - ], + src: ['bundle/tps-1@0.5x.json', 'bundle/tps-1.json'], data: { tags: { tps: true, @@ -229,18 +218,153 @@ describe('Manifest', () => alias: ['spine/dragon.json'], src: ['spine/dragon.json'], data: { - tags: {} + tags: {}, }, }, { alias: ['spine/dragon.atlas'], + src: ['spine/dragon@0.5x.atlas', 'spine/dragon.atlas'], + data: { + tags: { + spine: true, + }, + }, + }, + ], + }); + }, 30000); + + it('should copy over files and add them to manifest', async () => + { + const testName = 'manifest-copy'; + const inputDir = getInputDir(pkg, testName); + const outputDir = getOutputDir(pkg, testName); + + const useCache = false; + + createFolder(pkg, { + name: testName, + files: [], + + folders: [ + { + name: 'defaultFolder', + files: [ + { + name: 'json{copy}.json', + content: assetPath('json/json.json'), + }, + ], + folders: [ + { + name: 'tps{copy}', + files: genSprites(3), + folders: [], + }, + { + name: 'mip', + files: genSprites(3), + folders: [], + }, + ], + }, + ], + }); + + const assetpack = new AssetPack({ + entry: inputDir, + cacheLocation: getCacheDir(pkg, testName), + output: outputDir, + cache: useCache, + pipes: [ + mipmap(), + compress({ + png: true, + jpg: true, + webp: true, + avif: false, + }), + pixiManifest(), + ], + }); + + await assetpack.run(); + + // load the manifest json + const manifest = sortObjectProperties(await fs.readJSONSync(`${outputDir}/manifest.json`)) as any; + + expect(manifest.bundles[0]).toEqual({ + name: 'default', + assets: [ + { + alias: ['defaultFolder/json.json'], + src: ['defaultFolder/json.json'], + data: { + tags: { + copy: true, + }, + }, + }, + { + alias: ['defaultFolder/mip/sprite0.png'], + src: [ + 'defaultFolder/mip/sprite0@0.5x.webp', + 'defaultFolder/mip/sprite0@0.5x.png', + 'defaultFolder/mip/sprite0.webp', + 'defaultFolder/mip/sprite0.png', + ], + data: { + tags: {}, + }, + }, + { + alias: ['defaultFolder/mip/sprite1.png'], src: [ - 'spine/dragon@0.5x.atlas', - 'spine/dragon.atlas', + 'defaultFolder/mip/sprite1@0.5x.webp', + 'defaultFolder/mip/sprite1@0.5x.png', + 'defaultFolder/mip/sprite1.webp', + 'defaultFolder/mip/sprite1.png', ], + data: { + tags: {}, + }, + }, + { + alias: ['defaultFolder/mip/sprite2.png'], + src: [ + 'defaultFolder/mip/sprite2@0.5x.webp', + 'defaultFolder/mip/sprite2@0.5x.png', + 'defaultFolder/mip/sprite2.webp', + 'defaultFolder/mip/sprite2.png', + ], + data: { + tags: {}, + }, + }, + { + alias: ['defaultFolder/tps/sprite0.png'], + src: ['defaultFolder/tps/sprite0.png'], data: { tags: { - spine: true, + copy: true, + }, + }, + }, + { + alias: ['defaultFolder/tps/sprite1.png'], + src: ['defaultFolder/tps/sprite1.png'], + data: { + tags: { + copy: true, + }, + }, + }, + { + alias: ['defaultFolder/tps/sprite2.png'], + src: ['defaultFolder/tps/sprite2.png'], + data: { + tags: { + copy: true, }, }, }, @@ -323,7 +447,8 @@ describe('Manifest', () => }); const assetpack = new AssetPack({ - entry: inputDir, cacheLocation: getCacheDir(pkg, testName), + entry: inputDir, + cacheLocation: getCacheDir(pkg, testName), output: outputDir, cache: false, pipes: [ @@ -342,7 +467,7 @@ describe('Manifest', () => pixiManifest({ createShortcuts: true, trimExtensions: true, - includeMetaData: false + includeMetaData: false, }), spineAtlasManifestMod(), texturePackerManifestMod(), @@ -358,77 +483,39 @@ describe('Manifest', () => name: 'default', assets: [ { - alias: [ - 'folder/json.json', - 'json.json', - ], - src: [ - 'folder/json.json' - ] + alias: ['folder/json.json', 'json.json'], + src: ['folder/json.json'], }, { - alias: [ - 'folder/json.json5', - 'json.json5', - ], - src: [ - 'folder/json.json5' - ] + alias: ['folder/json.json5', 'json.json5'], + src: ['folder/json.json5'], }, { - alias: [ - 'folder/sprite.png', - 'folder/sprite', - 'sprite.png', - 'sprite' - ], + alias: ['folder/sprite.png', 'folder/sprite', 'sprite.png', 'sprite'], src: [ 'folder/sprite@0.5x.webp', 'folder/sprite@0.5x.png', 'folder/sprite.webp', 'folder/sprite.png', - ] + ], }, { - alias: [ - 'folder2/1.mp3', - 'folder2/1', - ], - src: [ - 'folder2/1.ogg', - 'folder2/1.mp3', - ] + alias: ['folder2/1.mp3', 'folder2/1'], + src: ['folder2/1.ogg', 'folder2/1.mp3'], }, { - alias: [ - 'folder2/folder3/1.mp3', - 'folder2/folder3/1', - ], - src: [ - 'folder2/folder3/1.ogg', - 'folder2/folder3/1.mp3', - ] + alias: ['folder2/folder3/1.mp3', 'folder2/folder3/1'], + src: ['folder2/folder3/1.ogg', 'folder2/folder3/1.mp3'], }, { - alias: [ - 'spine/dragon.json', - 'dragon.json', - ], - src: [ - 'spine/dragon.json' - ] + alias: ['spine/dragon.json', 'dragon.json'], + src: ['spine/dragon.json'], }, { - alias: [ - 'spine/dragon.atlas', - 'dragon.atlas', - ], - src: [ - 'spine/dragon@0.5x.atlas', - 'spine/dragon.atlas', - ] - } - ] + alias: ['spine/dragon.atlas', 'dragon.atlas'], + src: ['spine/dragon@0.5x.atlas', 'spine/dragon.atlas'], + }, + ], }); }); @@ -464,7 +551,8 @@ describe('Manifest', () => }); const assetpack = new AssetPack({ - entry: inputDir, cacheLocation: getCacheDir(pkg, testName), + entry: inputDir, + cacheLocation: getCacheDir(pkg, testName), output: outputDir, cache: false, pipes: [ @@ -477,7 +565,7 @@ describe('Manifest', () => pixiManifest({ createShortcuts: true, trimExtensions: false, - includeMetaData: false + includeMetaData: false, }), spineAtlasManifestMod(), texturePackerManifestMod(), @@ -487,23 +575,16 @@ describe('Manifest', () => await assetpack.run(); // load the manifest json - const manifest = sortObjectProperties((await fs.readJSONSync(`${outputDir}/manifest.json`))) as any; + const manifest = sortObjectProperties(await fs.readJSONSync(`${outputDir}/manifest.json`)) as any; expect(manifest.bundles[0]).toEqual({ - name: 'default', assets: [ { - alias: [ - 'spine/dragon.atlas', - 'dragon.atlas' - ], - src: [ - 'spine/dragon.atlas' - ] - } - ] - + alias: ['spine/dragon.atlas', 'dragon.atlas'], + src: ['spine/dragon.atlas'], + }, + ], }); }); @@ -582,7 +663,8 @@ describe('Manifest', () => }); const assetpack = new AssetPack({ - entry: inputDir, cacheLocation: getCacheDir(pkg, testName), + entry: inputDir, + cacheLocation: getCacheDir(pkg, testName), cache: false, output: outputDir, pipes: [ @@ -601,7 +683,7 @@ describe('Manifest', () => pixiManifest({ createShortcuts: true, trimExtensions: false, - includeMetaData: false + includeMetaData: false, }), spineAtlasManifestMod(), texturePackerManifestMod(), @@ -611,7 +693,7 @@ describe('Manifest', () => await assetpack.run(); // load the manifest json - const manifest = sortObjectProperties((await fs.readJSONSync(`${outputDir}/manifest.json`))) as any; + const manifest = sortObjectProperties(await fs.readJSONSync(`${outputDir}/manifest.json`)) as any; expect(manifest.bundles[0]).toEqual({ name: 'default', @@ -728,7 +810,8 @@ describe('Manifest', () => }); const assetpack = new AssetPack({ - entry: inputDir, cacheLocation: getCacheDir(pkg, testName), + entry: inputDir, + cacheLocation: getCacheDir(pkg, testName), output: outputDir, cache: false, pipes: [ @@ -747,7 +830,7 @@ describe('Manifest', () => pixiManifest({ createShortcuts: false, trimExtensions: true, - includeMetaData: false + includeMetaData: false, }), spineAtlasManifestMod(), texturePackerManifestMod(), @@ -757,78 +840,45 @@ describe('Manifest', () => await assetpack.run(); // load the manifest json - const manifest = sortObjectProperties((await fs.readJSONSync(`${outputDir}/manifest.json`))) as any; + const manifest = sortObjectProperties(await fs.readJSONSync(`${outputDir}/manifest.json`)) as any; expect(manifest.bundles[0]).toEqual({ name: 'default', assets: [ { - alias: [ - 'folder/json.json' - ], - src: [ - 'folder/json.json' - ] + alias: ['folder/json.json'], + src: ['folder/json.json'], }, { - alias: [ - 'folder/json.json5' - ], - src: [ - 'folder/json.json5' - ] + alias: ['folder/json.json5'], + src: ['folder/json.json5'], }, { - alias: [ - 'folder/sprite.png', - 'folder/sprite' - ], + alias: ['folder/sprite.png', 'folder/sprite'], src: [ 'folder/sprite@0.5x.webp', 'folder/sprite@0.5x.png', 'folder/sprite.webp', 'folder/sprite.png', - ] + ], }, { - alias: [ - 'folder2/1.mp3', - 'folder2/1' - ], - src: [ - 'folder2/1.ogg', - 'folder2/1.mp3', - ] + alias: ['folder2/1.mp3', 'folder2/1'], + src: ['folder2/1.ogg', 'folder2/1.mp3'], }, { - alias: [ - 'folder2/folder3/1.mp3', - 'folder2/folder3/1', - ], - src: [ - 'folder2/folder3/1.ogg', - 'folder2/folder3/1.mp3', - ] + alias: ['folder2/folder3/1.mp3', 'folder2/folder3/1'], + src: ['folder2/folder3/1.ogg', 'folder2/folder3/1.mp3'], }, { - alias: [ - 'spine/dragon.json' - ], - src: [ - 'spine/dragon.json' - ] + alias: ['spine/dragon.json'], + src: ['spine/dragon.json'], }, { - alias: [ - 'spine/dragon.atlas' - ], - src: [ - 'spine/dragon@0.5x.atlas', - 'spine/dragon.atlas', - ] - } - ] - + alias: ['spine/dragon.atlas'], + src: ['spine/dragon@0.5x.atlas', 'spine/dragon.atlas'], + }, + ], }); }); @@ -856,7 +906,8 @@ describe('Manifest', () => }); const assetpack = new AssetPack({ - entry: inputDir, cacheLocation: getCacheDir(pkg, testName), + entry: inputDir, + cacheLocation: getCacheDir(pkg, testName), output: outputDir, cache: false, pipes: [ @@ -907,12 +958,13 @@ describe('Manifest', () => }); const assetpack = new AssetPack({ - entry: inputDir, cacheLocation: getCacheDir(pkg, testName), + entry: inputDir, + cacheLocation: getCacheDir(pkg, testName), output: outputDir, cache: false, pipes: [ pixiManifest({ - includeMetaData: false + includeMetaData: false, }), ], }); @@ -923,59 +975,53 @@ describe('Manifest', () => bundles: [ { name: 'default', - assets: [] + assets: [], }, { name: 'sound2', assets: [ { - alias: [ - 'sound2/2.mp3' - ], - src: [ - 'sound2/2.mp3' - ] - } - ] + alias: ['sound2/2.mp3'], + src: ['sound2/2.mp3'], + }, + ], }, { name: 'sound', assets: [ { - alias: [ - 'sound/1.mp3' - ], - src: [ - 'sound/1.mp3' - ] - } - ] - } - ] + alias: ['sound/1.mp3'], + src: ['sound/1.mp3'], + }, + ], + }, + ], }); }); }); function sortObjectProperties(obj: any) { - return Object.keys(obj).sort().reduce((acc: any, key: string) => - { - const value = obj[key]; - - if (typeof value === 'object' && !Array.isArray(value) && value !== null) + return Object.keys(obj) + .sort() + .reduce((acc: any, key: string) => { - acc[key] = sortObjectProperties(value); - } - else - { - if (Array.isArray(value)) + const value = obj[key]; + + if (typeof value === 'object' && !Array.isArray(value) && value !== null) { - value.sort(); + acc[key] = sortObjectProperties(value); } + else + { + if (Array.isArray(value)) + { + value.sort(); + } - acc[key] = value; - } + acc[key] = value; + } - return acc; - }, {}); + return acc; + }, {}); } From 9c48d84ad5a0a310322ed531a8fe2e5ea4546a08 Mon Sep 17 00:00:00 2001 From: Zyie <24736175+Zyie@users.noreply.github.com> Date: Tue, 25 Jun 2024 09:57:49 +0100 Subject: [PATCH 2/3] feat: add mIgnore tag (#34) --- .eslintrc.cjs | 10 +++--- src/manifest/pixiManifest.ts | 35 ++++++++++++-------- src/spine/spineAtlasCacheBuster.ts | 4 ++- src/spine/spineAtlasManifestMod.ts | 4 ++- src/webfont/sdf.ts | 4 ++- test/manifest/Manifest.test.ts | 52 ++++++++++++++++++++++++++++++ test/webfont/Webfont.test.ts | 47 +++++++++++++++++++++++++-- 7 files changed, 133 insertions(+), 23 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index a7ae364..f455dbe 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -5,15 +5,17 @@ module.exports = { ecmaVersion: 2020, sourceType: "module", }, + plugins: ['import'], rules: { "spaced-comment": [1, "always", { markers: ["/"] }], "@typescript-eslint/triple-slash-reference": [1, { path: "always" }], - "@typescript-eslint/consistent-type-imports": [ - 1, - { disallowTypeAnnotations: false }, - ], "@typescript-eslint/type-annotation-spacing": 1, "@typescript-eslint/no-non-null-assertion": 0, + "@typescript-eslint/consistent-type-imports": + ["error", { disallowTypeAnnotations: false }], + "import/consistent-type-specifier-style": ["error", "prefer-top-level"], + "import/no-duplicates": ["error"], + "camelcase": 0, }, overrides: [ { diff --git a/src/manifest/pixiManifest.ts b/src/manifest/pixiManifest.ts index 9fc4f2e..bd630dd 100644 --- a/src/manifest/pixiManifest.ts +++ b/src/manifest/pixiManifest.ts @@ -1,10 +1,10 @@ import fs from 'fs-extra'; -import { - type Asset, - type AssetPipe, - path, - type PipeSystem, - stripTags +import { path, stripTags } from '../core/index.js'; + +import type { + Asset, + AssetPipe, + PipeSystem, PluginOptions } from '../core/index.js'; export interface PixiBundle @@ -28,7 +28,7 @@ export interface PixiManifestEntry }; } -export interface PixiManifestOptions +export interface PixiManifestOptions extends PluginOptions<'mIgnore' | 'manifest'> { output?: string; createShortcuts?: boolean; @@ -38,12 +38,16 @@ export interface PixiManifestOptions export function pixiManifest(_options: PixiManifestOptions = {}): AssetPipe { - const defaultOptions = { + const defaultOptions: PixiManifestOptions = { output: 'manifest.json', createShortcuts: false, trimExtensions: false, includeMetaData: true, - ..._options + ..._options, + tags: { + manifest: 'm', + mIgnore: 'mIgnore' + } }; return { @@ -98,7 +102,7 @@ function collectAssets( outputPath = '', entryPath = '', bundles: PixiBundle[], - bundle: PixiBundle, + bundle: PixiBundle ) { if (asset.skip) return; @@ -107,7 +111,7 @@ function collectAssets( let localBundle = bundle; - if (asset.metaData.m || asset.metaData.manifest) + if (asset.metaData[options.tags!.manifest!]) { localBundle = { name: stripTags(asset.filename), @@ -118,14 +122,17 @@ function collectAssets( } const bundleAssets = localBundle.assets; - const finalAssets = asset.getFinalTransformedChildren(); - if (asset.transformChildren.length > 0) + if (asset.transformChildren.length > 0 && !asset.inheritedMetaData[options.tags!.mIgnore!]) { + const nonIgnored = finalAssets.filter((finalAsset) => !finalAsset.inheritedMetaData[options.tags!.mIgnore!]); + + if (nonIgnored.length === 0) return; + bundleAssets.push({ alias: getShortNames(stripTags(path.relative(entryPath, asset.path)), options), - src: finalAssets + src: nonIgnored .map((finalAsset) => path.relative(outputPath, finalAsset.path)) .sort((a, b) => b.localeCompare(a)), data: options.includeMetaData ? { diff --git a/src/spine/spineAtlasCacheBuster.ts b/src/spine/spineAtlasCacheBuster.ts index 8c12799..2e17ab3 100644 --- a/src/spine/spineAtlasCacheBuster.ts +++ b/src/spine/spineAtlasCacheBuster.ts @@ -1,7 +1,9 @@ import fs from 'fs-extra'; -import { type Asset, type AssetPipe, checkExt, findAssets } from '../core/index.js'; +import { checkExt, findAssets } from '../core/index.js'; import { AtlasView } from './AtlasView.js'; +import type { Asset, AssetPipe } from '../core/index.js'; + /** * This should be used after the cache buster plugin in the pipes. * As it relies on the cache buster plugin to have already cache busted all files. diff --git a/src/spine/spineAtlasManifestMod.ts b/src/spine/spineAtlasManifestMod.ts index 83bf87d..2a99cd5 100644 --- a/src/spine/spineAtlasManifestMod.ts +++ b/src/spine/spineAtlasManifestMod.ts @@ -1,7 +1,9 @@ import fs from 'fs-extra'; -import { type Asset, type AssetPipe, findAssets, path } from '../core/index.js'; +import { findAssets, path } from '../core/index.js'; import { AtlasView } from './AtlasView.js'; +import type { Asset, AssetPipe } from '../core/index.js'; + export interface SpineManifestOptions { output?: string; diff --git a/src/webfont/sdf.ts b/src/webfont/sdf.ts index cbe8527..fa308ca 100644 --- a/src/webfont/sdf.ts +++ b/src/webfont/sdf.ts @@ -45,7 +45,9 @@ function signedFont( const newTextureAsset = createNewAssetAt(asset, newTextureName); // don't compress! - newTextureAsset.metaData.copy = true; + newTextureAsset.metaData[options.tags.nc] = true; + newTextureAsset.metaData[options.tags.fix] = true; + newTextureAsset.metaData.mIgnore = true; assets.push(newTextureAsset); diff --git a/test/manifest/Manifest.test.ts b/test/manifest/Manifest.test.ts index 96dfbbf..29ae8a8 100644 --- a/test/manifest/Manifest.test.ts +++ b/test/manifest/Manifest.test.ts @@ -998,6 +998,58 @@ describe('Manifest', () => ], }); }); + + it('should ignore files with the mIgnore tag', async () => + { + const testName = 'manifest-ignore'; + const inputDir = getInputDir(pkg, testName); + const outputDir = getOutputDir(pkg, testName); + + createFolder(pkg, { + name: testName, + files: [ + { + name: '1.png', + content: assetPath('image/sp-1.png'), + }, + { + name: '2{mIgnore}.png', + content: assetPath('image/sp-1.png'), + }, + ], + folders: [], + }); + + const assetpack = new AssetPack({ + entry: inputDir, + cacheLocation: getCacheDir(pkg, testName), + output: outputDir, + cache: false, + pipes: [ + pixiManifest({ + includeMetaData: false, + }), + ], + }); + + await assetpack.run(); + + const manifest = sortObjectProperties(await fs.readJSONSync(`${outputDir}/manifest.json`)); + + expect(manifest).toEqual({ + bundles: [ + { + name: 'default', + assets: [ + { + alias: ['1.png'], + src: ['1.png'], + }, + ], + }, + ], + }); + }); }); function sortObjectProperties(obj: any) diff --git a/test/webfont/Webfont.test.ts b/test/webfont/Webfont.test.ts index f694367..7c7ef5b 100644 --- a/test/webfont/Webfont.test.ts +++ b/test/webfont/Webfont.test.ts @@ -2,6 +2,8 @@ import fs from 'fs-extra'; import { existsSync } from 'node:fs'; import { describe, expect, it } from 'vitest'; import { AssetPack } from '../../src/core/index.js'; +import { compress } from '../../src/image/compress.js'; +import { mipmap } from '../../src/image/mipmap.js'; import { pixiManifest } from '../../src/manifest/index.js'; import { msdfFont, sdfFont, webfont } from '../../src/webfont/index.js'; import { assetPath, createFolder, getCacheDir, getInputDir, getOutputDir } from '../utils/index.js'; @@ -228,7 +230,7 @@ describe('Webfont', () => expect(existsSync(`${outputDir}/sdf.1.png`)).toBe(true); }); - it.skip('should generate manifest correctly', async () => + it('should generate manifest correctly', async () => { const testName = 'webfont-manifest'; const inputDir = getInputDir(pkg, testName); @@ -258,6 +260,26 @@ describe('Webfont', () => ], folders: [], }, + { + name: 'msdfFolder{msdf}', + files: [ + { + name: 'ttf.ttf', + content: assetPath('font/Roboto-Regular.ttf'), + }, + ], + folders: [], + }, + { + name: 'svgFolder{wf}', + files: [ + { + name: 'svg.svg', + content: assetPath('font/Roboto-Regular.svg'), + }, + ], + folders: [], + } ], }); @@ -266,8 +288,11 @@ describe('Webfont', () => output: outputDir, cache: false, pipes: [ - webfont(), // import is breaking definition file + webfont(), sdfFont(), + msdfFont(), + mipmap(), + compress(), pixiManifest(), ] }); @@ -289,6 +314,15 @@ describe('Webfont', () => } } }, + { + alias: ['msdfFolder/ttf.ttf'], + src: ['msdfFolder/ttf.fnt'], + data: { + tags: { + msdf: true, + } + } + }, { alias: ['sdfFolder/ttf.ttf'], src: ['sdfFolder/ttf.fnt'], @@ -298,6 +332,15 @@ describe('Webfont', () => } } }, + { + alias: ['svgFolder/svg.svg'], + src: ['svgFolder/svg.woff2'], + data: { + tags: { + wf: true, + } + } + }, ], }); }); From 0f210f57adeaad99a70216c1be08096b75d9f5a9 Mon Sep 17 00:00:00 2001 From: Zyie <24736175+Zyie@users.noreply.github.com> Date: Tue, 25 Jun 2024 10:02:52 +0100 Subject: [PATCH 3/3] feat: multi-pack spritesheets (#35) Co-authored-by: Mat Groves --- src/pixi/index.ts | 2 - src/texture-packer/index.ts | 1 - src/texture-packer/packer/createJsons.ts | 56 +++--- src/texture-packer/texturePacker.ts | 1 + .../texturePackerCacheBuster.ts | 20 ++- src/texture-packer/texturePackerCompress.ts | 35 +++- .../texturePackerManifestMod.ts | 167 ------------------ test/manifest/Manifest.test.ts | 32 ++-- .../texturePackerCacheBuster.test.ts | 90 ++++++++-- .../texturePackerManifest.test.ts | 32 ++-- test/webfont/Webfont.test.ts | 2 +- 11 files changed, 171 insertions(+), 267 deletions(-) delete mode 100644 src/texture-packer/texturePackerManifestMod.ts diff --git a/src/pixi/index.ts b/src/pixi/index.ts index 1afbc7c..54b22cd 100644 --- a/src/pixi/index.ts +++ b/src/pixi/index.ts @@ -12,7 +12,6 @@ import { spineAtlasMipmap } from '../spine/spineAtlasMipmap.js'; import { texturePacker } from '../texture-packer/texturePacker.js'; import { texturePackerCacheBuster } from '../texture-packer/texturePackerCacheBuster.js'; import { texturePackerCompress } from '../texture-packer/texturePackerCompress.js'; -import { texturePackerManifestMod } from '../texture-packer/texturePackerManifestMod.js'; import { webfont } from '../webfont/webfont.js'; import type { FfmpegOptions } from '../ffmpeg/ffmpeg.js'; @@ -109,7 +108,6 @@ export function pixiAssetPackPipes(config: PixiAssetPack) pipes.push( pixiManifest(manifestOptions), - texturePackerManifestMod(manifestOptions), spineAtlasManifestMod(manifestOptions), ); diff --git a/src/texture-packer/index.ts b/src/texture-packer/index.ts index 8958b40..477af01 100644 --- a/src/texture-packer/index.ts +++ b/src/texture-packer/index.ts @@ -1,4 +1,3 @@ export * from './texturePacker.js'; export * from './texturePackerCacheBuster.js'; export * from './texturePackerCompress.js'; -export * from './texturePackerManifestMod.js'; diff --git a/src/texture-packer/packer/createJsons.ts b/src/texture-packer/packer/createJsons.ts index f42d0ee..8c8144c 100644 --- a/src/texture-packer/packer/createJsons.ts +++ b/src/texture-packer/packer/createJsons.ts @@ -15,12 +15,12 @@ export function createJsons( width: number, height: number, options: { - textureName: string, - resolution: number, - textureFormat: 'png' | 'jpg', - nameStyle: 'short' | 'relative', - removeFileExtension: boolean - } + textureName: string; + resolution: number; + textureFormat: 'png' | 'jpg'; + nameStyle: 'short' | 'relative'; + removeFileExtension: boolean; + }, ) { const bins = packer.bins; @@ -32,7 +32,7 @@ export function createJsons( const bin = bins[i]; const json: any = { - frames: {} + frames: {}, }; for (let j = 0; j < bin.rects.length; j++) @@ -44,7 +44,7 @@ export function createJsons( x: rect.x, y: rect.y, w: rect.width, - h: rect.height + h: rect.height, }, rotated: rect.rot, trimmed: rect.textureData.trimmed, @@ -52,44 +52,44 @@ export function createJsons( x: rect.textureData.trimOffsetLeft, y: rect.textureData.trimOffsetTop, w: rect.width, - h: rect.height + h: rect.height, }, sourceSize: { w: rect.textureData.originalWidth, - h: rect.textureData.originalHeight - } + h: rect.textureData.originalHeight, + }, }; } json.meta = { app: 'http://github.com/pixijs/assetpack', version: '1.0', - image: createName( - options.textureName, - i, - bins.length !== 1, - options.resolution, - options.textureFormat - ), + image: createName(options.textureName, i, bins.length !== 1, options.resolution, options.textureFormat), format: 'RGBA8888', size: { w: width, - h: height + h: height, }, - scale: options.resolution + scale: options.resolution, + related_multi_packs: null, }; jsons.push({ - name: createName( - options.textureName, - i, - bins.length !== 1, - options.resolution, - 'json' - ), - json + name: createName(options.textureName, i, bins.length !== 1, options.resolution, 'json'), + json, }); } + // before we leave, lets connect all the jsons to the first json.. + + const firstJsonMeta = jsons[0].json.meta; + + firstJsonMeta.related_multi_packs = []; + + for (let i = 1; i < jsons.length; i++) + { + firstJsonMeta.related_multi_packs.push(jsons[i].name); + } + return jsons; } diff --git a/src/texture-packer/texturePacker.ts b/src/texture-packer/texturePacker.ts index eb08ce0..d494b10 100644 --- a/src/texture-packer/texturePacker.ts +++ b/src/texture-packer/texturePacker.ts @@ -159,6 +159,7 @@ export function texturePacker(_options: TexturePackerOptions = {}): AssetPipe asset.getFinalTransformedChildren()[0]); - jsonAssets.forEach((jsonAsset) => + // loop through all the json files back to front + for (let i = jsonAssets.length - 1; i >= 0; i--) { // we are going to replace the textures in the atlas file with the new cache busted textures // as we do this, the hash of the atlas file will change, so we need to update the path // and also remove the original file. - + const jsonAsset = jsonAssets[i]; const originalHash = jsonAsset.hash; const originalPath = jsonAsset.path; @@ -75,15 +76,24 @@ export function texturePackerCacheBuster( json.meta.image = cacheBustedTexture.filename; - jsonAsset.buffer = Buffer.from(JSON.stringify(json)); + if (json.meta.related_multi_packs) + { + json.meta.related_multi_packs = (json.meta.related_multi_packs as string[]).map((pack) => + { + const foundAssets = findAssets((asset) => + asset.filename === pack, asset, true); - jsonAsset.path = jsonAsset.path.replace(originalHash, jsonAsset.hash); + return foundAssets[0].getFinalTransformedChildren()[0].filename; + }); + } + jsonAsset.buffer = Buffer.from(JSON.stringify(json)); + jsonAsset.path = jsonAsset.path.replace(originalHash, jsonAsset.hash); fs.removeSync(originalPath); // rewrite.. fs.writeFileSync(jsonAsset.path, jsonAsset.buffer); - }); + } textureJsonFilesToFix.length = 0; } diff --git a/src/texture-packer/texturePackerCompress.ts b/src/texture-packer/texturePackerCompress.ts index d7cdecb..54b85fa 100644 --- a/src/texture-packer/texturePackerCompress.ts +++ b/src/texture-packer/texturePackerCompress.ts @@ -5,7 +5,9 @@ import type { CompressOptions } from '../image/compress.js'; export type TexturePackerCompressOptions = PluginOptions<'tps' | 'nc'> & Omit; -export function texturePackerCompress(_options?: TexturePackerCompressOptions): AssetPipe +export function texturePackerCompress( + _options?: TexturePackerCompressOptions, +): AssetPipe { const defaultOptions = { ...{ @@ -17,8 +19,8 @@ export function texturePackerCompress(_options?: TexturePackerCompressOptions): tags: { tps: 'tps', nc: 'nc', - ..._options?.tags - } + ..._options?.tags, + }, }; return { @@ -26,17 +28,19 @@ export function texturePackerCompress(_options?: TexturePackerCompressOptions): defaultOptions, test(asset: Asset, options) { - return (asset.allMetaData[options.tags.tps] + return ( + asset.allMetaData[options.tags.tps] && !asset.allMetaData[options.tags.nc] - && checkExt(asset.path, '.json')); + && checkExt(asset.path, '.json') + ); }, async transform(asset: Asset, options) { const formats = []; - if (options.avif)formats.push('avif'); - if (options.png)formats.push('png'); - if (options.webp)formats.push('webp'); + if (options.avif) formats.push('avif'); + if (options.png) formats.push('png'); + if (options.webp) formats.push('webp'); const json = JSON.parse(asset.buffer.toString()); @@ -49,8 +53,21 @@ export function texturePackerCompress(_options?: TexturePackerCompressOptions): json.meta.image = swapExt(json.meta.image, extension); const newAsset = createNewAssetAt(asset, newFileName); + const newJson = JSON.parse(JSON.stringify(json)); + + if (newJson.meta.related_multi_packs) + { + newJson.meta.related_multi_packs = (newJson.meta.related_multi_packs as string[]).map((pack) => + swapExt(pack, `${extension}.json`), + ); + } + + newAsset.buffer = Buffer.from(JSON.stringify(newJson, null, 2)); - newAsset.buffer = Buffer.from(JSON.stringify(json, null, 2)); + if (!newJson.meta.related_multi_packs) + { + newAsset.metaData.mIgnore = true; + } return newAsset; }); diff --git a/src/texture-packer/texturePackerManifestMod.ts b/src/texture-packer/texturePackerManifestMod.ts deleted file mode 100644 index b6b53aa..0000000 --- a/src/texture-packer/texturePackerManifestMod.ts +++ /dev/null @@ -1,167 +0,0 @@ -import fs from 'fs-extra'; -import { findAssets, Logger, path } from '../core/index.js'; - -import type { Asset, AssetPipe, PluginOptions } from '../core/index.js'; - -export interface TexturePackerManifestOptions extends PluginOptions<'tps'> -{ - output?: string; -} - -/** - * This pipe will modify the manifest generated by 'pixiManifest'. It will remove the entry - * in the manifest - which groups all the textures and jsons under one asset and replace it with - * the assets representing individual pages of the sprite sheet. - * - * Once done, it rewrites the manifest. - * - * This should be added after the `pixiManifest` pipe. - * - * ensure that the same output path is passed to the pipe as the `pixiManifest` pipe. Otherwise - * the manifest will not be found. - * - * As this pipe needs to know about all the textures in the texture files most of the work is done - * in the finish method. - * - * Kind of like applying a patch at the end of the manifest process. - * - * @param _options - * @returns - */ -export function texturePackerManifestMod( - _options: TexturePackerManifestOptions = {} -): AssetPipe -{ - const defaultOptions = { - output: 'manifest.json', - ..._options, - tags: { - tps: 'tps', - ..._options.tags, - }, - }; - - return { - folder: false, - name: 'texture-packer-manifest', - defaultOptions, - - async finish(asset: Asset, options, pipeSystem) - { - const manifestLocation = options.output; - - const newFileName = path.dirname(manifestLocation) === '.' - ? path.joinSafe(pipeSystem.outputPath, manifestLocation) : manifestLocation; - - if (!fs.existsSync(newFileName)) - { - // eslint-disable-next-line max-len - Logger.warn(`[AssetPack][texture-packer-manifest] Texture Packer Manifest could not find the manifest: ${newFileName}. Please ensure that the 'pixiManifest' output and the 'texturePackerManifest' output are the same.`); - - return; - } - - const manifest = fs.readJsonSync(newFileName); - - // used to make sure we don't process the same asset twice. - const duplicateHash: Record = {}; - - const originalJsonAssets = findAssets((asset) => - asset.metaData[options.tags.tps] && !asset.transformParent, asset, true); - - originalJsonAssets.forEach((originalJsonAsset) => - { - // if we have already processed this asset then skip it. - if (duplicateHash[originalJsonAsset.path]) return; - - duplicateHash[originalJsonAsset.path] = true; - - // now get all the final assets that were created for this sprite sheet. - // this will include all the variations of the textures and the jsons. - const finalJsonAssets = originalJsonAsset.getFinalTransformedChildren(); - - // next find the manifestAsset data that was added by the manifest - this is the data that - // we need to remove and replace with the new data for each PAGE of the sprite sheet. - const jsonManifestPath = path.relative(pipeSystem.outputPath, finalJsonAssets[0].path); - - const { manifestAsset, bundle } = findManifestAsset(manifest, jsonManifestPath); - - const texturePackedAssets = getTexturePackedAssets(finalJsonAssets); - - // now we need to get the pages of the sprite sheet and update the manifest with the new pages. - texturePackedAssets.forEach((pages, pageIndex) => - { - bundle.assets.push({ - // use the same alias as the original asset but add the page index to it. - // we don't control what the alias is so we use whats here. - alias: manifestAsset.alias.map((alias: string) => - getAlias(alias, pageIndex, texturePackedAssets.length > 1) - ), - src: pages - .map((finalAsset) => path.relative(pipeSystem.outputPath, finalAsset.path)) - .sort((a, b) => b.localeCompare(a)), - data: manifestAsset.data - }); - }); - - // to wrap up remove the original manifest asset from the bundle. - bundle.assets.splice(bundle.assets.indexOf(manifestAsset), 1); - }); - - // write the new manifest. - fs.writeJSONSync(newFileName, manifest, { spaces: 2 }); - - return; - } - }; -} - -function getTexturePackedAssets(assets: Asset[]) -{ - // first get the jsons.. - const jsonAssets = assets.filter((asset) => asset.extension === '.json'); - - const groupAssets: Asset[][] = []; - - for (let i = 0; i < jsonAssets.length; i++) - { - const jsonAsset = jsonAssets[i]; - - groupAssets[jsonAsset.transformData.page] ??= []; - - groupAssets[jsonAsset.transformData.page].push(jsonAsset); - } - - return groupAssets; -} - -function findManifestAsset(manifest: any, assetPath: string): {bundle: any, manifestAsset: any} -{ - for (let i = 0; i < manifest.bundles.length; i++) - { - const bundle = manifest.bundles[i]; - const assets = bundle.assets; - - const manifestAsset = assets.find((asset: {src: string[]}) => - - asset.src.includes(assetPath) - ); - - if (manifestAsset) - { - return { bundle, manifestAsset }; - } - } - - return { bundle: null, manifestAsset: null }; -} - -function getAlias(alias: string, pageIndex: number, multiPage: boolean) -{ - if (multiPage) - { - return `${alias}-${pageIndex}`; - } - - return alias; -} diff --git a/test/manifest/Manifest.test.ts b/test/manifest/Manifest.test.ts index 29ae8a8..cd29400 100644 --- a/test/manifest/Manifest.test.ts +++ b/test/manifest/Manifest.test.ts @@ -6,7 +6,7 @@ import { audio } from '../../src/ffmpeg/index.js'; import { compress, mipmap } from '../../src/image/index.js'; import { pixiManifest } from '../../src/manifest/index.js'; import { spineAtlasManifestMod, spineAtlasMipmap } from '../../src/spine/index.js'; -import { texturePacker, texturePackerManifestMod } from '../../src/texture-packer/index.js'; +import { texturePacker, texturePackerCompress } from '../../src/texture-packer/index.js'; import { assetPath, createFolder, getCacheDir, getInputDir, getOutputDir } from '../utils/index.js'; import type { File } from '../utils/index.js'; @@ -115,13 +115,13 @@ describe('Manifest', () => output: outputDir, cache: useCache, pipes: [ + audio(), + spineAtlasMipmap(), texturePacker({ resolutionOptions: { maximumTextureSize: 512, }, }), - audio(), - spineAtlasMipmap(), mipmap(), compress({ png: true, @@ -129,9 +129,9 @@ describe('Manifest', () => webp: true, avif: false, }), + texturePackerCompress(), pixiManifest(), spineAtlasManifestMod(), - texturePackerManifestMod(), ], }); @@ -176,18 +176,11 @@ describe('Manifest', () => }, }, { - alias: ['bundle/tps-0'], - src: ['bundle/tps-0@0.5x.json', 'bundle/tps-0.json'], - data: { - tags: { - tps: true, - m: true, - }, - }, - }, - { - alias: ['bundle/tps-1'], - src: ['bundle/tps-1@0.5x.json', 'bundle/tps-1.json'], + alias: ['bundle/tps'], + src: ['bundle/tps-0@0.5x.webp.json', + 'bundle/tps-0@0.5x.png.json', + 'bundle/tps-0.webp.json', + 'bundle/tps-0.png.json'], data: { tags: { tps: true, @@ -232,7 +225,7 @@ describe('Manifest', () => }, ], }); - }, 30000); + }); it('should copy over files and add them to manifest', async () => { @@ -307,6 +300,7 @@ describe('Manifest', () => }, { alias: ['defaultFolder/mip/sprite0.png'], + src: [ 'defaultFolder/mip/sprite0@0.5x.webp', 'defaultFolder/mip/sprite0@0.5x.png', @@ -470,7 +464,6 @@ describe('Manifest', () => includeMetaData: false, }), spineAtlasManifestMod(), - texturePackerManifestMod(), ], }); @@ -568,7 +561,6 @@ describe('Manifest', () => includeMetaData: false, }), spineAtlasManifestMod(), - texturePackerManifestMod(), ], }); @@ -686,7 +678,6 @@ describe('Manifest', () => includeMetaData: false, }), spineAtlasManifestMod(), - texturePackerManifestMod(), ], }); @@ -833,7 +824,6 @@ describe('Manifest', () => includeMetaData: false, }), spineAtlasManifestMod(), - texturePackerManifestMod(), ], }); diff --git a/test/texture-packer/texturePackerCacheBuster.test.ts b/test/texture-packer/texturePackerCacheBuster.test.ts index 8b04212..1ff9b36 100644 --- a/test/texture-packer/texturePackerCacheBuster.test.ts +++ b/test/texture-packer/texturePackerCacheBuster.test.ts @@ -3,8 +3,10 @@ import { glob } from 'glob'; import { describe, expect, it } from 'vitest'; import { cacheBuster } from '../../src/cache-buster/index.js'; import { AssetPack } from '../../src/core/index.js'; +import { compress } from '../../src/image/compress.js'; import { texturePacker } from '../../src/texture-packer/texturePacker.js'; import { texturePackerCacheBuster } from '../../src/texture-packer/texturePackerCacheBuster.js'; +import { texturePackerCompress } from '../../src/texture-packer/texturePackerCompress.js'; import { createTPSFolder } from '../utils/createTPSFolder.js'; import { getCacheDir, getInputDir, getOutputDir } from '../utils/index.js'; @@ -28,6 +30,7 @@ describe('Texture Packer Cache Buster', () => texturePacker({ resolutionOptions: { resolutions: { default: 1 }, + maximumTextureSize: 512, }, }), cacheBuster(), @@ -41,9 +44,9 @@ describe('Texture Packer Cache Buster', () => const files = await glob(globPath); // need two sets of files - expect(files.length).toBe(2); - expect(files.filter((file) => file.endsWith('.json')).length).toBe(1); - expect(files.filter((file) => file.endsWith('.png')).length).toBe(1); + expect(files.length).toBe(4); + expect(files.filter((file) => file.endsWith('.json')).length).toBe(2); + expect(files.filter((file) => file.endsWith('.png')).length).toBe(2); const jsonFiles = files.filter((file) => file.endsWith('.json')); const pngFiles = files.filter((file) => file.endsWith('.png')); @@ -53,18 +56,81 @@ describe('Texture Packer Cache Buster', () => { const rawJson = fs.readJSONSync(jsonFile); - const checkFiles = (fileList: string[]) => + expect(pngFiles.includes(`${outputDir}/${rawJson.meta.image}`)).toBe(true); + + // check if json has related_multi_packs + if (rawJson.meta.related_multi_packs) + { + const relatedMultiPacks = rawJson.meta.related_multi_packs as string[]; + + expect(relatedMultiPacks.length).toBe(1); + expect(jsonFiles.includes(`${outputDir}/${relatedMultiPacks[0]}`)).toBe(true); + } + }); + }); + + it('should create compressed sprite sheet and correctly update json', async () => + { + const testName = 'tp-cache-bust-compress'; + const inputDir = getInputDir(pkg, testName); + const outputDir = getOutputDir(pkg, testName); + + createTPSFolder(testName, pkg); + + const assetpack = new AssetPack({ + entry: inputDir, cacheLocation: getCacheDir(pkg, testName), + output: outputDir, + cache: false, + pipes: [ + texturePacker({ + resolutionOptions: { + resolutions: { default: 1 }, + maximumTextureSize: 512, + }, + }), + compress(), + texturePackerCompress(), + cacheBuster(), + texturePackerCacheBuster() + ] + }); + + await assetpack.run(); + + const globPath = `${outputDir}/*.{json,png,webp}`; + const files = await glob(globPath); + + expect(files.length).toBe(8); + expect(files.filter((file) => file.endsWith('.json')).length).toBe(4); + expect(files.filter((file) => file.endsWith('.png')).length).toBe(2); + expect(files.filter((file) => file.endsWith('.webp')).length).toBe(2); + + const jsonFiles = files.filter((file) => file.endsWith('.json')); + const pngFiles = files.filter((file) => file.endsWith('.png')); + const webpFiles = files.filter((file) => file.endsWith('.webp')); + + // check that the files are correct + jsonFiles.forEach((jsonFile) => + { + const rawJson = fs.readJSONSync(jsonFile); + + if (rawJson.meta.image.includes('.webp')) { - fileList.forEach((file) => - { - // remove the outputDir - file = file.replace(`${outputDir}/`, ''); + expect(webpFiles.includes(`${outputDir}/${rawJson.meta.image}`)).toBe(true); + } + else + { + expect(pngFiles.includes(`${outputDir}/${rawJson.meta.image}`)).toBe(true); + } - expect(rawJson.meta.image).toEqual(file); - }); - }; + // check if json has related_multi_packs + if (rawJson.meta.related_multi_packs) + { + const relatedMultiPacks = rawJson.meta.related_multi_packs as string[]; - checkFiles(pngFiles); + expect(relatedMultiPacks.length).toBe(1); + expect(jsonFiles.includes(`${outputDir}/${relatedMultiPacks[0]}`)).toBe(true); + } }); }); }); diff --git a/test/texture-packer/texturePackerManifest.test.ts b/test/texture-packer/texturePackerManifest.test.ts index b36ee2f..f7c626e 100644 --- a/test/texture-packer/texturePackerManifest.test.ts +++ b/test/texture-packer/texturePackerManifest.test.ts @@ -1,9 +1,9 @@ import fs from 'fs-extra'; import { describe, expect, it } from 'vitest'; import { AssetPack } from '../../src/core/index.js'; +import { compress } from '../../src/image/compress.js'; import { pixiManifest } from '../../src/manifest/index.js'; -import { texturePacker } from '../../src/texture-packer/index.js'; -import { texturePackerManifestMod } from '../../src/texture-packer/texturePackerManifestMod.js'; +import { texturePacker, texturePackerCompress } from '../../src/texture-packer/index.js'; import { createTPSFolder } from '../utils/createTPSFolder.js'; import { getCacheDir, getInputDir, getOutputDir } from '../utils/index.js'; @@ -30,7 +30,6 @@ describe('Texture Packer Compression', () => }, }), pixiManifest(), - texturePackerManifestMod(), ] }); @@ -70,12 +69,13 @@ describe('Texture Packer Compression', () => pipes: [ texturePacker({ resolutionOptions: { - resolutions: { default: 1 }, - maximumTextureSize: 512 + resolutions: { default: 1, low: 0.5 }, + maximumTextureSize: 512, }, }), + compress(), + texturePackerCompress(), pixiManifest(), - texturePackerManifestMod(), ] }); @@ -86,10 +86,13 @@ describe('Texture Packer Compression', () => expect(manifest.bundles[0].assets).toEqual([ { alias: [ - 'sprites-0' + 'sprites' ], src: [ - 'sprites-0.json' + 'sprites-0@0.5x.webp.json', + 'sprites-0@0.5x.png.json', + 'sprites-0.webp.json', + 'sprites-0.png.json', ], data: { tags: { @@ -97,19 +100,6 @@ describe('Texture Packer Compression', () => } } }, - { - alias: [ - 'sprites-1' - ], - src: [ - 'sprites-1.json' - ], - data: { - tags: { - tps: true - } - } - } ]); }); }); diff --git a/test/webfont/Webfont.test.ts b/test/webfont/Webfont.test.ts index 7c7ef5b..b924fc9 100644 --- a/test/webfont/Webfont.test.ts +++ b/test/webfont/Webfont.test.ts @@ -343,5 +343,5 @@ describe('Webfont', () => }, ], }); - }); + }, 10000); });