Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow tags to be added manifest data directly #82

Merged
merged 9 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 40 additions & 3 deletions packages/assetpack/src/core/Asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export class Asset

metaData: Record<string, any> = {};
inheritedMetaData: Record<string, any> = {};
allMetaData: Record<string, any> = {};
transformData: Record<string, any> = {};

settings?: Record<string, any>;
Expand Down Expand Up @@ -63,7 +62,6 @@ export class Asset
asset.parent = this;

asset.inheritedMetaData = { ...this.inheritedMetaData, ...this.metaData };
asset.allMetaData = { ...asset.inheritedMetaData, ...asset.metaData };
asset.transformData = { ...this.transformData, ...asset.transformData };
}

Expand All @@ -87,12 +85,16 @@ export class Asset
asset.transformParent = this;

asset.inheritedMetaData = { ...this.inheritedMetaData, ...this.metaData };
asset.allMetaData = { ...asset.inheritedMetaData, ...asset.metaData };
asset.transformData = { ...this.transformData, ...asset.transformData };

asset.settings = this.settings;
}

get allMetaData()
{
return { ...this.inheritedMetaData, ...this.metaData };
}

get state()
{
return this._state;
Expand Down Expand Up @@ -251,5 +253,40 @@ export class Asset
this.children[i].releaseChildrenBuffers();
}
}

/**
* Get the public meta data for this asset
* This will exclude any internal data
*/
getPublicMetaData(internalPipeData: Record<string, any>)
{
const internalKeys = new Set(Object.keys(internalPipeData));
const metaData = Object.keys(this.allMetaData).reduce((result: Record<string, any>, key) =>
{
if (!internalKeys.has(key))
{
result[key] = this.allMetaData[key];
}

return result;
}, {} as Record<string, any>);

return metaData;
}

getInternalMetaData(internalPipeData: Record<string, any>)
{
const res: Record<string, any> = {};

Object.keys(internalPipeData).forEach((key) =>
{
if (this.allMetaData[key])
{
res[key] = this.allMetaData[key];
}
});

return res;
}
}

7 changes: 6 additions & 1 deletion packages/assetpack/src/core/pipes/AssetPipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type DeepRequired<T> = T extends Primitive
};
export interface PluginOptions {}

export interface AssetPipe<OPTIONS=Record<string, any>, TAGS extends string = string>
export interface AssetPipe<OPTIONS=Record<string, any>, TAGS extends string = string, INTERNAL_TAGS extends string = string>
{
/** Whether the process runs on a folder */
folder?: boolean;
Expand All @@ -31,6 +31,11 @@ export interface AssetPipe<OPTIONS=Record<string, any>, TAGS extends string = st
/** Tags that can be used to control the plugin */
tags?: Record<TAGS, string>;

/**
* Any tags here will not be placed in the manifest data.
*/
internalTags?: Record<INTERNAL_TAGS, string>;

/**
* Called once at the start.
* @param asser - the root asset
Expand Down
6 changes: 6 additions & 0 deletions packages/assetpack/src/core/pipes/PipeSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ export class PipeSystem

assetSettings: AssetSettings[] = [];

internalMetaData: Record<string, any> = {
copy: 'copy',
ignore: 'ignore',
};

constructor(options: PipeSystemOptions)
{
const pipes = [];
Expand All @@ -49,6 +54,7 @@ export class PipeSystem
options.pipes.flat().forEach((pipe) =>
{
this.pipeHash[pipe.name] = pipe;
this.internalMetaData = { ...this.internalMetaData, ...Object.values(pipe.internalTags ?? pipe.tags ?? {}).reduce((acc, tag) => ({ ...acc, [tag]: true }), {}) };
});

this.pipes = pipes;
Expand Down
2 changes: 1 addition & 1 deletion packages/assetpack/src/image/compress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export function compress(options: CompressOptions = {}): AssetPipe<CompressOptio
},
async transform(asset: Asset, options)
{
const shouldCompress = compress && !asset.metaData.nc;
const shouldCompress = compress && !asset.metaData[this.tags!.nc];
Zyie marked this conversation as resolved.
Show resolved Hide resolved

if (!shouldCompress)
{
Expand Down
62 changes: 56 additions & 6 deletions packages/assetpack/src/manifest/pixiManifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,49 @@ export interface PixiManifestEntry

export interface PixiManifestOptions extends PluginOptions
{
/**
* The output location for the manifest file.
*/
output?: string;
/**
* if true, the alias will be created with the basename of the file.
*/
createShortcuts?: boolean;
/**
* if true, the extensions will be removed from the alias names.
*/
trimExtensions?: boolean;
/**
* if true, the metaData will be outputted in the data field of the manifest.
*/
includeMetaData?: boolean;
/**
* if true, the all tags will be outputted in the data.tags field of the manifest.
* If false, only internal tags will be outputted to the data.tags field. All other tags will be outputted to the data field directly.
* @example
* ```json
* {
* "bundles": [
* {
* "name": "default",
* "assets": [
* {
* "alias": ["test"],
* "src": ["test.png"],
* "data": {
* "tags": {
* "nc": true,
* "customTag": true // this tag will be outputted to the data field directly instead of the data.tags field
* }
* }
* }
* ]
* }
* ]
* }
* @default true
*/
legacyMetaDataOutput?: boolean;
}

export function pixiManifest(_options: PixiManifestOptions = {}): AssetPipe<PixiManifestOptions, 'manifest' | 'mIgnore'>
Expand All @@ -45,6 +84,7 @@ export function pixiManifest(_options: PixiManifestOptions = {}): AssetPipe<Pixi
createShortcuts: false,
trimExtensions: false,
includeMetaData: true,
legacyMetaDataOutput: true,
..._options,
},
tags: {
Expand Down Expand Up @@ -72,7 +112,8 @@ export function pixiManifest(_options: PixiManifestOptions = {}): AssetPipe<Pixi
pipeSystem.entryPath,
manifest.bundles,
defaultBundle,
this.tags!
this.tags!,
pipeSystem.internalMetaData
);
filterUniqueNames(manifest);
await fs.writeJSON(newFileName, manifest, { spaces: 2 });
Expand Down Expand Up @@ -109,7 +150,8 @@ function collectAssets(
entryPath = '',
bundles: PixiBundle[],
bundle: PixiBundle,
tags: AssetPipe<null, 'manifest' | 'mIgnore'>['tags']
tags: AssetPipe<null, 'manifest' | 'mIgnore'>['tags'],
internalTags: Record<string, any>
)
{
if (asset.skip) return;
Expand Down Expand Up @@ -137,20 +179,28 @@ function collectAssets(

if (finalManifestAssets.length === 0) return;

const metadata = {
tags: { ...asset.getInternalMetaData(internalTags) },
...asset.getPublicMetaData(internalTags)
} as Record<string, any>;

if (options.legacyMetaDataOutput)
{
metadata.tags = asset.allMetaData;
}

bundleAssets.push({
alias: getShortNames(stripTags(path.relative(entryPath, asset.path)), options),
src: finalManifestAssets
.map((finalAsset) => path.relative(outputPath, finalAsset.path))
.sort((a, b) => b.localeCompare(a)),
data: options.includeMetaData ? {
tags: asset.allMetaData
} : undefined
data: options.includeMetaData ? metadata : undefined
});
}

asset.children.forEach((child) =>
{
collectAssets(child, options, outputPath, entryPath, bundles, localBundle, tags);
collectAssets(child, options, outputPath, entryPath, bundles, localBundle, tags, internalTags);
});

// for all assets.. check for atlas and remove them from the bundle..
Expand Down
4 changes: 3 additions & 1 deletion packages/assetpack/src/webfont/sdf.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from 'fs-extra';
import generateBMFont from 'msdf-bmfont-xml';
import { checkExt, createNewAssetAt, stripTags } from '../core/index.js';
import { checkExt, createNewAssetAt, path, stripTags } from '../core/index.js';

import type { BitmapFontOptions } from 'msdf-bmfont-xml';
import type { Asset, AssetPipe, PluginOptions } from '../core/index.js';
Expand Down Expand Up @@ -33,6 +33,8 @@ function signedFont(
{
const newFileName = stripTags(asset.filename.replace(/\.(ttf)$/i, ''));

// set the family name to the filename if it doesn't exist
asset.metaData.family ??= path.trimExt(asset.filename);
const { font, textures } = await GenerateFont(asset.path, {
...options.font,
filename: newFileName,
Expand Down
6 changes: 4 additions & 2 deletions packages/assetpack/src/webfont/webfont.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ export function webfont(): AssetPipe<any, 'wf'>
buffer = fonts.svg.to.woff2(asset.path);
break;
default:
throw new Error(`{Assetpack] Unsupported font type: ${ext}`);
break;
throw new Error(`{AssetPack] Unsupported font type: ${ext}`);
}

const newFileName = asset.filename.replace(/\.(otf|ttf|svg)$/i, '.woff2');
Expand All @@ -44,6 +43,9 @@ export function webfont(): AssetPipe<any, 'wf'>

newAsset.buffer = buffer;

// set the family name to the filename if it doesn't exist
asset.metaData.family ??= path.trimExt(asset.filename);

return [newAsset];
}
};
Expand Down
1 change: 1 addition & 0 deletions packages/assetpack/test/manifest/Manifest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ describe('Manifest', () =>
alias: ['spine/dragon.atlas'],
src: ['spine/[email protected]', 'spine/dragon.atlas'],
data: {
spine: true,
tags: {
spine: true,
},
Expand Down
3 changes: 3 additions & 0 deletions packages/assetpack/test/spine/spineAtlasManifest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ describe('Atlas Manifest', () =>
'dragon.atlas'
],
data: {
spine: true,
tags: {
spine: true
}
Expand Down Expand Up @@ -182,6 +183,7 @@ describe('Atlas Manifest', () =>
'dragon.atlas'
],
data: {
spine: true,
tags: {
spine: true
}
Expand All @@ -206,6 +208,7 @@ describe('Atlas Manifest', () =>
'nested/dragon.atlas'
],
data: {
spine: true,
tags: {
spine: true
}
Expand Down
14 changes: 9 additions & 5 deletions packages/assetpack/test/webfont/Webfont.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ describe('Webfont', () =>
msdfFont(),
mipmap(),
compress(),
pixiManifest(),
pixiManifest({ legacyMetaDataOutput: false }),
]
});

Expand All @@ -309,36 +309,40 @@ describe('Webfont', () =>
alias: ['defaultFolder/ttf.ttf'],
src: ['defaultFolder/ttf.woff2'],
data: {
family: 'ttf',
tags: {
wf: true,
}
},
}
},
{
alias: ['msdfFolder/ttf.ttf'],
src: ['msdfFolder/ttf.fnt'],
data: {
family: 'ttf',
tags: {
msdf: true,
}
},
}
},
{
alias: ['sdfFolder/ttf.ttf'],
src: ['sdfFolder/ttf.fnt'],
data: {
family: 'ttf',
tags: {
sdf: true,
}
},
}
},
{
alias: ['svgFolder/svg.svg'],
src: ['svgFolder/svg.woff2'],
data: {
family: 'svg',
tags: {
wf: true,
}
},
}
},
],
Expand Down
11 changes: 9 additions & 2 deletions packages/docs/docs/guide/pipes/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,12 @@ Each plugin has its own set of tags, so be sure to check the documentation for t
### Other Tag Examples

- You can also add multiple tags to a single asset, like this `asset{tag1}{tag2}`.
- Tags can have data appended to them, like this `asset{tag1:myData}`.
- Tags can have multiple data values, like this `asset{tag1:100,200}`.
- Tags can have data appended to them, like this `asset{tag1=myData}`.
- Tags can have multiple data values, like this `asset{tag1=100&200}`.

### Data Tags

Data tags are a special type of tag that a plugin can specify to allow for the value of that tag to be passed to the manifest.
This can be useful for PixiJS as in the manifest you can specify certain properties for each asset.

For example, the webfont plugin has a `family` tag that can be used to specify the font family name of the font file.
Loading