adonis-responsive-attachment
Advanced tools
Comparing version 1.6.0 to 1.7.0
@@ -7,6 +7,6 @@ /// <reference types="@adonisjs/drive/build/adonis-typings" /> | ||
declare module '@ioc:Adonis/Addons/ResponsiveAttachment' { | ||
import { ColumnOptions } from '@ioc:Adonis/Lucid/Orm'; | ||
import { LoggerContract } from '@ioc:Adonis/Core/Logger'; | ||
import { MultipartFileContract } from '@ioc:Adonis/Core/BodyParser'; | ||
import { DisksList, ContentHeaders, DriverContract, DriveManagerContract } from '@ioc:Adonis/Core/Drive'; | ||
import type { ColumnOptions } from '@ioc:Adonis/Lucid/Orm'; | ||
import type { LoggerContract } from '@ioc:Adonis/Core/Logger'; | ||
import type { MultipartFileContract } from '@ioc:Adonis/Core/BodyParser'; | ||
import type { DisksList, ContentHeaders, DriverContract, DriveManagerContract } from '@ioc:Adonis/Core/Drive'; | ||
type Breakpoints = Partial<{ | ||
@@ -32,3 +32,9 @@ large: number | 'off'; | ||
preComputeUrls?: boolean | ((disk: DriverContract, attachment: ResponsiveAttachmentContract) => Promise<UrlRecords>); | ||
blurhash?: BlurhashOptions; | ||
}; | ||
type BlurhashOptions = { | ||
enabled: boolean; | ||
componentX?: number; | ||
componentY?: number; | ||
}; | ||
interface ImageAttributes { | ||
@@ -58,2 +64,3 @@ /** | ||
* The hash string of the image | ||
* @deprecated Will be removed in later versions | ||
*/ | ||
@@ -70,2 +77,6 @@ hash?: string; | ||
/** | ||
* The blurhash of the image | ||
*/ | ||
blurhash?: string; | ||
/** | ||
* The format of the image | ||
@@ -72,0 +83,0 @@ */ |
@@ -12,2 +12,5 @@ /// <reference types="node" /> | ||
fileName?: string; | ||
/** | ||
* @deprecated Will be removed in later versions | ||
*/ | ||
hash?: string; | ||
@@ -21,2 +24,3 @@ extname?: string; | ||
height?: number; | ||
blurhash?: string; | ||
/** | ||
@@ -23,0 +27,0 @@ * The image format used by sharp to force conversion |
@@ -5,8 +5,33 @@ /// <reference types="@adonisjs/validator" /> | ||
interface Rules { | ||
/** | ||
* Ensure image width does not exceed the specified width. | ||
* | ||
* Provided by the Adonis Responsive Attachment addon. | ||
*/ | ||
maxImageWidth(value: number): Rule; | ||
/** | ||
* Ensure image height does not exceed the specified height. | ||
* | ||
* Provided by the Adonis Responsive Attachment addon. | ||
*/ | ||
maxImageHeight(value: number): Rule; | ||
/** | ||
* Ensure image width is above the specified width. | ||
* | ||
* Provided by the Adonis Responsive Attachment addon. | ||
*/ | ||
minImageWidth(value: number): Rule; | ||
/** | ||
* Ensure image height is above the specified height. | ||
* | ||
* Provided by the Adonis Responsive Attachment addon. | ||
*/ | ||
minImageHeight(value: number): Rule; | ||
/** | ||
* Ensure image aspect ratio matches the specified aspect ratio | ||
* | ||
* Provided by the Adonis Responsive Attachment addon. | ||
*/ | ||
imageAspectRatio(value: number): Rule; | ||
} | ||
} |
@@ -15,2 +15,3 @@ "use strict"; | ||
const index_1 = require("./index"); | ||
const image_manipulation_helper_1 = require("../Helpers/image_manipulation_helper"); | ||
/** | ||
@@ -180,2 +181,3 @@ * Default breakpoint options | ||
Model.boot(); | ||
const enableBlurhash = (0, image_manipulation_helper_1.getDefaultBlurhashOptions)(options); | ||
/** | ||
@@ -206,2 +208,3 @@ * Separate attachment options from the column options | ||
disableThumbnail, | ||
blurhash: enableBlurhash, | ||
}, | ||
@@ -208,0 +211,0 @@ }); |
@@ -82,2 +82,3 @@ /// <reference path="../../adonis-typings/index.d.ts" /> | ||
* The image hash. | ||
* @deprecated Will be removed in later versions | ||
*/ | ||
@@ -94,2 +95,6 @@ hash?: string; | ||
/** | ||
* The image's blurhash. | ||
*/ | ||
blurhash?: string; | ||
/** | ||
* This file name. | ||
@@ -129,2 +134,3 @@ */ | ||
buffer: Buffer | undefined; | ||
blurhash: string | undefined; | ||
}; | ||
@@ -131,0 +137,0 @@ /** |
@@ -21,3 +21,3 @@ "use strict"; | ||
const lodash_1 = require("lodash"); | ||
const ImageManipulationHelper_1 = require("../Helpers/ImageManipulationHelper"); | ||
const image_manipulation_helper_1 = require("../Helpers/image_manipulation_helper"); | ||
exports.tempUploadFolder = 'image_upload_tmp'; | ||
@@ -61,3 +61,3 @@ /** | ||
} | ||
if (ImageManipulationHelper_1.allowedFormats.includes(file?.subtype) === false) { | ||
if (image_manipulation_helper_1.allowedFormats.includes(file?.subtype) === false) { | ||
throw new RangeError(`Uploaded file is not an allowable image. Make sure that you uploaded only the following format: "jpeg", "png", "webp", "tiff", and "avif".`); | ||
@@ -97,3 +97,3 @@ } | ||
const subtype = mime.split('/').pop(); | ||
if (ImageManipulationHelper_1.allowedFormats.includes(subtype) === false) { | ||
if (image_manipulation_helper_1.allowedFormats.includes(subtype) === false) { | ||
throw new RangeError(`Uploaded file is not an allowable image. Make sure that you uploaded only the following format: "jpeg", "png", "webp", "tiff", and "avif".`); | ||
@@ -156,2 +156,3 @@ } | ||
this.format = attributes.format; | ||
this.blurhash = attributes.blurhash; | ||
this.height = attributes.height; | ||
@@ -178,2 +179,3 @@ this.extname = attributes.extname; | ||
buffer: this.buffer, | ||
blurhash: this.blurhash, | ||
}; | ||
@@ -210,2 +212,3 @@ } | ||
disk: this.options?.disk, | ||
blurhash: (0, image_manipulation_helper_1.getDefaultBlurhashOptions)(this.options), | ||
}, options); | ||
@@ -217,3 +220,3 @@ return this; | ||
// and the info of the image | ||
const { buffer, info } = await (0, ImageManipulationHelper_1.optimize)(this.buffer, this.options); | ||
const { buffer, info } = await (0, image_manipulation_helper_1.optimize)(this.buffer, this.options); | ||
// Override the `imageInfo` object with the optimised `info` object | ||
@@ -228,2 +231,3 @@ // As the optimised `info` object is preferred | ||
async save() { | ||
const OPTIONS = (0, image_manipulation_helper_1.getMergedOptions)(this.options || {}); | ||
try { | ||
@@ -245,12 +249,11 @@ /** | ||
*/ | ||
this.name = | ||
this.options?.keepOriginal ?? true | ||
? (0, ImageManipulationHelper_1.generateName)({ | ||
extname: enhancedImageData.extname, | ||
hash: enhancedImageData.hash, | ||
options: this.options, | ||
prefix: 'original', | ||
fileName: this.fileName, | ||
}) | ||
: undefined; | ||
this.name = OPTIONS.keepOriginal | ||
? (0, image_manipulation_helper_1.generateName)({ | ||
extname: enhancedImageData.extname, | ||
hash: enhancedImageData.hash, | ||
options: OPTIONS, | ||
prefix: 'original', | ||
fileName: this.fileName, | ||
}) | ||
: undefined; | ||
/** | ||
@@ -260,3 +263,3 @@ * Update the local attributes with the attributes | ||
*/ | ||
if (this.options?.keepOriginal ?? true) { | ||
if (OPTIONS.keepOriginal) { | ||
this.size = enhancedImageData.size; | ||
@@ -278,3 +281,3 @@ this.hash = enhancedImageData.hash; | ||
*/ | ||
if (this.options?.keepOriginal ?? true) { | ||
if (OPTIONS.keepOriginal) { | ||
await this.getDisk().put(enhancedImageData.name, enhancedImageData.buffer); | ||
@@ -285,4 +288,11 @@ } | ||
*/ | ||
const thumbnailImageData = await (0, ImageManipulationHelper_1.generateThumbnail)(enhancedImageData, this.options); | ||
const thumbnailImageData = await (0, image_manipulation_helper_1.generateThumbnail)(enhancedImageData, OPTIONS); | ||
if (thumbnailImageData) { | ||
// Set blurhash to top-level image data | ||
this.blurhash = thumbnailImageData.blurhash; | ||
// Set the blurhash to the enhanced image data | ||
enhancedImageData.blurhash = thumbnailImageData.blurhash; | ||
} | ||
const thumbnailIsRequired = OPTIONS.responsiveDimensions && !OPTIONS.disableThumbnail; | ||
if (thumbnailImageData && thumbnailIsRequired) { | ||
/** | ||
@@ -301,3 +311,3 @@ * Write the thumbnail image to the disk | ||
*/ | ||
const breakpointFormats = await (0, ImageManipulationHelper_1.generateBreakpointImages)(enhancedImageData, this.options); | ||
const breakpointFormats = await (0, image_manipulation_helper_1.generateBreakpointImages)(enhancedImageData, OPTIONS); | ||
if (breakpointFormats && Array.isArray(breakpointFormats) && breakpointFormats.length > 0) { | ||
@@ -319,3 +329,3 @@ for (const format of breakpointFormats) { | ||
} | ||
const { width, height } = await (0, ImageManipulationHelper_1.getDimensions)(enhancedImageData.buffer); | ||
const { width, height } = await (0, image_manipulation_helper_1.getDimensions)(enhancedImageData.buffer); | ||
delete enhancedImageData.buffer; | ||
@@ -329,3 +339,3 @@ (0, lodash_1.assign)(enhancedImageData, { | ||
*/ | ||
if (this.options?.keepOriginal ?? true) { | ||
if (OPTIONS.keepOriginal) { | ||
this.width = enhancedImageData.width; | ||
@@ -365,2 +375,3 @@ this.height = enhancedImageData.height; | ||
async delete() { | ||
const OPTIONS = (0, image_manipulation_helper_1.getMergedOptions)(this.options || {}); | ||
try { | ||
@@ -373,3 +384,3 @@ if (!this.isPersisted) { | ||
*/ | ||
if (this.options?.keepOriginal ?? true) | ||
if (OPTIONS.keepOriginal) | ||
await this.getDisk().delete(this.name); | ||
@@ -376,0 +387,0 @@ /** |
@@ -15,3 +15,3 @@ "use strict"; | ||
const utils_1 = require("@poppinss/utils"); | ||
const ImageManipulationHelper_1 = require("../Helpers/ImageManipulationHelper"); | ||
const image_manipulation_helper_1 = require("../Helpers/image_manipulation_helper"); | ||
var ImageDimensionsValidationRule; | ||
@@ -58,3 +58,3 @@ (function (ImageDimensionsValidationRule) { | ||
const imageBuffer = await (0, promises_1.readFile)(file.tmpPath); | ||
const { width, height } = await (0, ImageManipulationHelper_1.getMetaData)(imageBuffer); | ||
const { width, height } = await (0, image_manipulation_helper_1.getMetaData)(imageBuffer); | ||
const reportError = () => { | ||
@@ -61,0 +61,0 @@ errorReporter.report(pointer, this.ruleName, `${this.ruleName} validation failure`, arrayExpressionPointer); |
{ | ||
"name": "adonis-responsive-attachment", | ||
"version": "1.6.0", | ||
"version": "1.7.0", | ||
"description": "Generate and persist optimised and responsive breakpoint images on the fly in your AdonisJS application.", | ||
@@ -96,2 +96,3 @@ "main": "build/providers/ResponsiveAttachmentProvider.js", | ||
"@poppinss/utils": "^5.0.0", | ||
"blurhash": "^2.0.5", | ||
"detect-file-type": "^0.2.8", | ||
@@ -98,0 +99,0 @@ "lodash": "^4.17.21", |
@@ -46,2 +46,4 @@ # Adonis Responsive Attachment | ||
- Ability to create attachments from file buffers. This is very helpful when you want to persist images outside of the HTTP life-cycle. | ||
- Provides validation rules for checking image dimensions and aspect ratio. | ||
- Provides blurhash generation (https://blurha.sh/) | ||
@@ -246,6 +248,7 @@ ## Pre-requisites | ||
6. `optimizeOrientation` - boolean, | ||
7. `responsiveDimensions` - boolean, | ||
7. `responsiveDimensions` - boolean | Option, | ||
8. `preComputeUrls` - boolean, | ||
9. `disableThumbnail` - boolean. | ||
10. `keepOriginal` - boolean. | ||
11. `blurhash` - Option | ||
@@ -511,2 +514,35 @@ Let's discuss these options | ||
### 11. The `blurhash` Option | ||
The `blurhash` option is used to enable, disable, and customise the generation of blurhashes (https://blurha.sh/) for the generated responsive formats. Blurhash generation is disabled by default. | ||
Below is the type for the blurhash option. | ||
```typescript | ||
type BlurhashOptions = { | ||
enabled: boolean | ||
componentX?: number | ||
componentY?: number | ||
} | ||
``` | ||
For more about `componentX` and `componentY` properties [read here](https://github.com/woltapp/blurhash?tab=readme-ov-file#how-do-i-pick-the-number-of-x-and-y-components). | ||
A responsive format with blurhash looks like this: | ||
```javascript | ||
{ | ||
name: 'small_avatar_clt8v5bva00267fi1542b3axb.jpg', | ||
hash: 'clt8v5bva00267fi1542b3axb', | ||
extname: 'jpg', | ||
mimeType: 'image/jpeg', | ||
format: 'jpeg', | ||
width: 500, | ||
height: 333, | ||
size: 36.98, | ||
blurhash: 'LnEM,?t7RPbIt:axadj[M|WAj[j[' | ||
} | ||
``` | ||
Note that when blurhash is disabled, the `blurhash` property will be `undefined` before serialisation and missing after serialisation. | ||
## Generating URLs | ||
@@ -513,0 +549,0 @@ |
106875
1876
843
7
+ Addedblurhash@^2.0.5
+ Added@types/node@20.12.11(transitive)
+ Addedblurhash@2.0.5(transitive)
- Removed@types/node@20.12.12(transitive)