From 85d5a314277717b44fb65d8db2a4c2bbf6d46abc Mon Sep 17 00:00:00 2001 From: Zyie <24736175+Zyie@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:32:01 +0100 Subject: [PATCH] feat: add global `copy` tag --- 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; + }, {}); }