Skip to content

Commit

Permalink
asset pack refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
GoodBoyDigital committed Mar 15, 2024
1 parent 1329c52 commit 84e9ed7
Show file tree
Hide file tree
Showing 87 changed files with 3,881 additions and 3,052 deletions.
25 changes: 25 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!-- IMPORTANT! Read [the contributing guide](../blob/master/CONTRIBUTING.md) before opening the PR for review. -->

## Context and Summary

<!-- Document the context, summary or any other information relating to this PR. The purpose is to provide with the reviewer a clear technical overview/headsup for this PR. This can also be any technical explanation to why the original issues or specs is implemented this way. -->

<!-- For Bug fixes, document how/why bugs happened and how the fix actually fix the bug. -->

## Link to Issues

<!-- Links to github issues. If there is a spec append spec links here too. -->

## Verification and Test Notes

<!-- Document unit tests added, cases covered, proposed end to end testing (if needed), and manual verification steps taken, including links to Amplitude dashboards when Analytics are affected. -->

## PR Checklist

- [ ] Context and Summary about the why and what
- [ ] Document how/why bug happened and fixed
- [ ] Code matches coding standards (call out any exceptions)
- [ ] Unit tests have been added/updated to provide complete coverage for the code in this PR
- [ ] Documentation has been updated appropriately
- [ ] Are all test passing (`npm run test`)

2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ Thumbs.db
.eslintcache
.testInput
.testOutput
.assetpack
.asset-pack
5 changes: 5 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
globals: {
'ts-jest': {
diagnostics: false,
}
},
testPathIgnorePatterns: ['/node_modules/', '/src/', '/dist/'],
testTimeout: 300000,
moduleNameMapper: {
Expand Down
40 changes: 29 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
"@types/jest": "^29.4.0",
"eslint": "^8.33.0",
"find-up": "^5.0.0",
"fs-extra": "^11.1.0",
"husky": "^8.0.3",
"jest": "^29.4.1",
"jest-extended": "^3.2.3",
Expand All @@ -51,5 +50,10 @@
"ts-jest": "^29.0.5",
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
},
"dependencies": {
"chokidar": "^3.5.3",
"eventemitter3": "^5.0.1",
"fs-extra": "^11.1.0"
}
}
54 changes: 0 additions & 54 deletions packages/compress/src/avif.ts

This file was deleted.

120 changes: 26 additions & 94 deletions packages/compress/src/compress.ts
Original file line number Diff line number Diff line change
@@ -1,105 +1,37 @@
import type { Plugin, PluginOptions } from '@assetpack/core';
import { hasTag } from '@assetpack/core';
import type { AssetPipe, PluginOptions } from '@assetpack/core';
import { multiPipe } from '@assetpack/core';
import type { WebpOptions, PngOptions, AvifOptions, JpegOptions } from 'sharp';
import { compression } from './compressions';
import { webpDefaults } from './webp';
import { pngDefaults } from './png';
import { avifDefaults } from './avif';
import { jpgDefaults } from './jpg';
import { compressAvif } from './compressAvif';
import { compressJpg } from './compressJpg';
import { compressWebp } from './compressWebp';
import { compressPng } from './compressPng';

export interface CompressOptions extends PluginOptions<'nc'>
{
webp: Omit<WebpOptions, 'force'> | false
png: Omit<PngOptions, 'force'> | false
avif: Omit<AvifOptions, 'force'> | false
jpg: Omit<JpegOptions, 'force'> | false
webp?: Omit<WebpOptions, 'force'> | false
png?: Omit<PngOptions, 'force'> | false
avif?: Omit<AvifOptions, 'force'> | false
jpg?: Omit<JpegOptions, 'force'> | false
}

// converts png, jpg, jpeg
export function compress(options?: Partial<CompressOptions>): Plugin<CompressOptions>
export function compress(options: Partial<CompressOptions> = {}): AssetPipe
{
const combineOptions = (type: keyof CompressOptions, defaults: WebpOptions | PngOptions | AvifOptions | JpegOptions) =>
{
if (options?.[type] === false) return false;

return {
...defaults,
...options?.[type]
};
};

const defaultOptions: Required<CompressOptions> = {
webp: combineOptions('webp', webpDefaults),
png: combineOptions('png', pngDefaults),
avif: combineOptions('avif', avifDefaults),
jpg: combineOptions('jpg', jpgDefaults),
tags: {
nc: 'nc',
...options?.tags
}
const tags = {
nc: 'nc',
...options?.tags
};

return {
folder: false,
test(tree, _p, opts)
{
const tags = { ...defaultOptions.tags, ...opts.tags } as Required<CompressOptions['tags']>;
const nc = hasTag(tree, 'path', tags.nc);

if (nc) return false;

for (const key in compression.test)
{
// skip if the plugin is disabled
if (
opts[key as keyof typeof opts] === false
|| defaultOptions[key as keyof typeof defaultOptions] === false
) continue;

const testFn = compression.test[key as keyof typeof compression.test];

if (testFn(tree.path)) return true;
}

return false;
},
async post(tree, processor, options)
{
const promises: Promise<void>[] = [];

for (const key in compression.test)
{
// skip if the plugin is disabled
if (
options[key as keyof typeof options] === false
|| defaultOptions[key as keyof typeof defaultOptions] === false
) continue;

const testFn = compression.test[key as keyof typeof compression.test];

if (testFn(tree.path))
{
// now we convert the file
const opts = {
...defaultOptions[key as keyof typeof defaultOptions],
...options[key as keyof typeof options]
};

promises.push(new Promise(async (resolve) =>
{
const res = await compression.compress.to[
key as keyof typeof compression.compress.to
](tree.path, opts);
// now we save the file

compression.save.to[key as keyof typeof compression.save.to](tree.path, res, processor, tree);

resolve();
}));
}
}

await Promise.all(promises);
}
};
const compressionPipes = [
...(options.png === false ? [] : [compressPng({ compression: options.png, tags })]),
...(options.jpg === false ? [] : [compressJpg({ compression: options.jpg, tags })]),
...(options.webp === false ? [] : [compressWebp({ compression: options.webp, tags })]),
...(options.avif === false ? [] : [compressAvif({ compression: options.avif, tags })])
];

return multiPipe({
pipes: compressionPipes,
name: 'compress'
});
}

47 changes: 47 additions & 0 deletions packages/compress/src/compressAvif.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { AssetPipe, Asset, PluginOptions } from '@assetpack/core';
import { checkExt, createNewAssetAt } from '@assetpack/core';
import type { AvifOptions } from 'sharp';
import sharp from 'sharp';
import { writeFile } from 'fs-extra';

interface CompressAvifOptions extends PluginOptions<'nc'>
{
compression?: Omit<AvifOptions, 'force'>;
}

export function compressAvif(_options: CompressAvifOptions = {}): AssetPipe
{
const defaultOptions = {
compression: {
..._options?.compression
},

tags: {
nc: 'nc',
..._options?.tags
}
};

return {
name: 'avif',
folder: false,
defaultOptions,
test: (asset: Asset, options) =>
!asset.allMetaData[options.tags.nc] && checkExt(asset.path, '.png', '.jpg', '.jpeg'),

transform: async (asset: Asset, options) =>
{
const newFileName = asset.filename.replace(/\.(png|jpg|jpeg)$/i, '.avif');

const newAsset = createNewAssetAt(asset, newFileName);

const buffer = await sharp(asset.path)
.avif({ ...options.compression, force: true })
.toBuffer();

await writeFile(newAsset.path, buffer);

return [newAsset];
}
};
}
Loading

0 comments on commit 84e9ed7

Please sign in to comment.