mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Merge pull request #787 from directus/assets
Assets fixes and improvements.
This commit is contained in:
@@ -3,37 +3,37 @@ import { Transformation } from './types/assets';
|
||||
export const SYSTEM_ASSET_ALLOW_LIST: Transformation[] = [
|
||||
{
|
||||
key: 'system-small-cover',
|
||||
w: 64,
|
||||
h: 64,
|
||||
f: 'cover',
|
||||
width: 64,
|
||||
height: 64,
|
||||
fit: 'cover',
|
||||
},
|
||||
{
|
||||
key: 'system-small-contain',
|
||||
w: 64,
|
||||
f: 'contain',
|
||||
width: 64,
|
||||
fit: 'contain',
|
||||
},
|
||||
{
|
||||
key: 'system-medium-cover',
|
||||
w: 300,
|
||||
h: 300,
|
||||
f: 'cover',
|
||||
width: 300,
|
||||
height: 300,
|
||||
fit: 'cover',
|
||||
},
|
||||
{
|
||||
key: 'system-medium-contain',
|
||||
w: 300,
|
||||
f: 'contain',
|
||||
width: 300,
|
||||
fit: 'contain',
|
||||
},
|
||||
{
|
||||
key: 'system-large-cover',
|
||||
w: 800,
|
||||
h: 600,
|
||||
f: 'cover',
|
||||
width: 800,
|
||||
height: 600,
|
||||
fit: 'cover',
|
||||
},
|
||||
{
|
||||
key: 'system-large-contain',
|
||||
w: 800,
|
||||
f: 'contain',
|
||||
width: 800,
|
||||
fit: 'contain',
|
||||
},
|
||||
];
|
||||
|
||||
export const ASSET_TRANSFORM_QUERY_KEYS = ['key', 'w', 'h', 'f'];
|
||||
export const ASSET_TRANSFORM_QUERY_KEYS = ['key', 'width', 'height', 'fit', 'withoutEnlargement'];
|
||||
|
||||
@@ -9,7 +9,6 @@ import { Transformation } from '../types/assets';
|
||||
import storage from '../storage';
|
||||
import { PayloadService, AssetsService } from '../services';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
import { respond } from '../middleware/respond';
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -79,18 +78,20 @@ router.get(
|
||||
];
|
||||
|
||||
// For use in the next request handler
|
||||
res.locals.shortcuts = [...SYSTEM_ASSET_ALLOW_LIST, assetSettings.storage_asset_presets];
|
||||
res.locals.shortcuts = [
|
||||
...SYSTEM_ASSET_ALLOW_LIST,
|
||||
...(assetSettings.storage_asset_presets || []),
|
||||
];
|
||||
res.locals.transformation = transformation;
|
||||
|
||||
if (Object.keys(transformation).length === 0) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (assetSettings.asset_generation === 'all') {
|
||||
if (assetSettings.storage_asset_transform === 'all') {
|
||||
if (transformation.key && allKeys.includes(transformation.key as string) === false)
|
||||
throw new InvalidQueryException(`Key "${transformation.key}" isn't configured.`);
|
||||
return next();
|
||||
} else if (assetSettings.asset_generation === 'shortcut') {
|
||||
} else if (assetSettings.storage_asset_transform === 'shortcut') {
|
||||
if (allKeys.includes(transformation.key as string)) return next();
|
||||
throw new InvalidQueryException(
|
||||
`Only configured shortcuts can be used in asset generation.`
|
||||
|
||||
@@ -132,6 +132,11 @@ fields:
|
||||
text: Contain (preserve aspect ratio)
|
||||
- value: cover
|
||||
text: Cover (forces exact size)
|
||||
- value: inside
|
||||
text: Fit inside
|
||||
- value: outside
|
||||
text: Fit outside
|
||||
required: true
|
||||
width: half
|
||||
- field: width
|
||||
name: Width
|
||||
@@ -161,7 +166,17 @@ fields:
|
||||
max: 100
|
||||
min: 0
|
||||
step: 1
|
||||
width: full
|
||||
required: true
|
||||
width: half
|
||||
- field: withoutEnlargement
|
||||
type: boolean
|
||||
schema:
|
||||
default_value: false
|
||||
meta:
|
||||
interface: toggle
|
||||
width: half
|
||||
options:
|
||||
label: Don't upscale images
|
||||
template: '{{key}}'
|
||||
special: json
|
||||
width: full
|
||||
|
||||
@@ -48,9 +48,11 @@ export class AssetsService {
|
||||
private parseTransformation(transformation: Transformation): ResizeOptions {
|
||||
const resizeOptions: ResizeOptions = {};
|
||||
|
||||
if (transformation.w) resizeOptions.width = Number(transformation.w);
|
||||
if (transformation.h) resizeOptions.height = Number(transformation.h);
|
||||
if (transformation.f) resizeOptions.fit = transformation.f;
|
||||
if (transformation.width) resizeOptions.width = Number(transformation.width);
|
||||
if (transformation.height) resizeOptions.height = Number(transformation.height);
|
||||
if (transformation.fit) resizeOptions.fit = transformation.fit;
|
||||
if (transformation.withoutEnlargement)
|
||||
resizeOptions.withoutEnlargement = Boolean(transformation.withoutEnlargement);
|
||||
|
||||
return resizeOptions;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export type Transformation = {
|
||||
key?: string;
|
||||
w?: number; // width
|
||||
h?: number; // height
|
||||
f?: 'cover' | 'contain'; // fit
|
||||
width?: number; // width
|
||||
height?: number; // height
|
||||
fit?: 'cover' | 'contain' | 'inside' | 'outside'; // fit
|
||||
withoutEnlargement?: boolean; // Without Enlargement
|
||||
};
|
||||
|
||||
// @NOTE Keys used in Transformation should match ASSET_GENERATION_QUERY_KEYS in constants.ts
|
||||
|
||||
@@ -11364,7 +11364,9 @@
|
||||
"options": {
|
||||
"choices": {
|
||||
"contain": "Contain (preserve aspect ratio)",
|
||||
"crop": "Crop (forces exact size)"
|
||||
"crop": "Crop (forces exact size)",
|
||||
"inside": "Fit inside",
|
||||
"outside": "Fit outside"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
@@ -11387,6 +11389,18 @@
|
||||
"type": "integer",
|
||||
"width": "half"
|
||||
},
|
||||
{
|
||||
"default_value": false,
|
||||
"field": "withoutEnlargement",
|
||||
"interface": "toggle",
|
||||
"name": "Don't upscale images",
|
||||
"required": false,
|
||||
"type": "boolean",
|
||||
"width": "half",
|
||||
"options": {
|
||||
"label": "Don't upscale images"
|
||||
}
|
||||
},
|
||||
{
|
||||
"default_value": 80,
|
||||
"field": "quality",
|
||||
@@ -11399,7 +11413,7 @@
|
||||
},
|
||||
"required": true,
|
||||
"type": "integer",
|
||||
"width": "full"
|
||||
"width": "half"
|
||||
}
|
||||
],
|
||||
"template": "{{key}}"
|
||||
|
||||
162
app/package-lock.json
generated
162
app/package-lock.json
generated
@@ -6601,6 +6601,51 @@
|
||||
"tslint": "^5.20.1",
|
||||
"webpack": "^4.0.0",
|
||||
"yorkie": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"fork-ts-checker-webpack-plugin-v5": {
|
||||
"version": "npm:fork-ts-checker-webpack-plugin@5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.2.0.tgz",
|
||||
"integrity": "sha512-NEKcI0+osT5bBFZ1SFGzJMQETjQWZrSvMO1g0nAR/w0t328Z41eN8BJEIZyFCl2HsuiJpa9AN474Nh2qLVwGLQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.8.3",
|
||||
"@types/json-schema": "^7.0.5",
|
||||
"chalk": "^4.1.0",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"fs-extra": "^9.0.0",
|
||||
"memfs": "^3.1.2",
|
||||
"minimatch": "^3.0.4",
|
||||
"schema-utils": "2.7.0",
|
||||
"semver": "^7.3.2",
|
||||
"tapable": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
|
||||
"integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.4",
|
||||
"ajv": "^6.12.2",
|
||||
"ajv-keywords": "^3.4.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@vue/cli-plugin-unit-jest": {
|
||||
@@ -6740,6 +6785,17 @@
|
||||
"unique-filename": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
||||
@@ -6823,6 +6879,18 @@
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
@@ -6936,6 +7004,18 @@
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
|
||||
"dev": true
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.0.0-beta.8",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.8.tgz",
|
||||
"integrity": "sha512-oouKUQWWHbSihqSD7mhymGPX1OQ4hedzAHyvm8RdyHh6m3oIvoRF+NM45i/bhNOlo8jCnuJhaSUf/6oDjv978g==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||
@@ -11664,51 +11744,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"fork-ts-checker-webpack-plugin-v5": {
|
||||
"version": "npm:fork-ts-checker-webpack-plugin@5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.2.0.tgz",
|
||||
"integrity": "sha512-NEKcI0+osT5bBFZ1SFGzJMQETjQWZrSvMO1g0nAR/w0t328Z41eN8BJEIZyFCl2HsuiJpa9AN474Nh2qLVwGLQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.8.3",
|
||||
"@types/json-schema": "^7.0.5",
|
||||
"chalk": "^4.1.0",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"fs-extra": "^9.0.0",
|
||||
"memfs": "^3.1.2",
|
||||
"minimatch": "^3.0.4",
|
||||
"schema-utils": "2.7.0",
|
||||
"semver": "^7.3.2",
|
||||
"tapable": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
|
||||
"integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.4",
|
||||
"ajv": "^6.12.2",
|
||||
"ajv-keywords": "^3.4.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
@@ -20342,43 +20377,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.0.0-beta.8",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.8.tgz",
|
||||
"integrity": "sha512-oouKUQWWHbSihqSD7mhymGPX1OQ4hedzAHyvm8RdyHh6m3oIvoRF+NM45i/bhNOlo8jCnuJhaSUf/6oDjv978g==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "3.4.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.6.tgz",
|
||||
|
||||
@@ -40,14 +40,16 @@ The **Storage Asset Transform** can be used in conjunction with the presets to f
|
||||
|
||||
Fetching thumbnails is as easy as adding query parameters to the original file's URL. If a requested thumbnail doesn't yet exist, it is dynamically generated and immediately returned. When requesting a thumbnail, the following parameters are all required.
|
||||
|
||||
* **`f`** — The **fit** of the thumbnail, either `crop` or `contain`
|
||||
* **`w`** — The **width** of the thumbnail in pixels
|
||||
* **`h`** — The **height** of the thumbnail in pixels
|
||||
* **`q`** — The **quality** of the thumbnail (`0` to `100`)
|
||||
* **`fit`** — The **fit** of the thumbnail, either `crop` or `contain`
|
||||
* **`width`** — The **width** of the thumbnail in pixels
|
||||
* **`height`** — The **height** of the thumbnail in pixels
|
||||
* **`quality`** — The **quality** of the thumbnail (`0` to `100`)
|
||||
* **`withoutEnlargement`** — Disable image up-scaling
|
||||
* **`download`** — Add `Content-Disposition` header and force browser to download file
|
||||
|
||||
```
|
||||
example.com/assets/<file-id>?f=<fit>&w=<width>&h=<height>&q=<quality>
|
||||
example.com/assets/1ac73658-8b62-4dea-b6da-529fbc9d01a4?f=crop&w=200&h=200&q=80
|
||||
example.com/assets/<file-id>?fit=<fit>&width=<width>&height=<height>&quality=<quality>
|
||||
example.com/assets/1ac73658-8b62-4dea-b6da-529fbc9d01a4?fit=crop&width=200&height=200&quality=80
|
||||
```
|
||||
|
||||
Alternatively, you can reference a specific thumbnail by its preset key.
|
||||
|
||||
@@ -71,12 +71,17 @@ properties:
|
||||
enum:
|
||||
- cover
|
||||
- contain
|
||||
- inside
|
||||
- outside
|
||||
width:
|
||||
description: Width of the thumbnail.
|
||||
type: integer
|
||||
height:
|
||||
description: Height of the thumbnail.
|
||||
type: integer
|
||||
withoutEnlargement:
|
||||
description: No image upscale
|
||||
type: boolean
|
||||
quality:
|
||||
description: Quality of the compression used.
|
||||
type: integer
|
||||
|
||||
@@ -32,7 +32,12 @@ get:
|
||||
description: Fit of the file
|
||||
schema:
|
||||
type: string
|
||||
enum: [crop, contain]
|
||||
enum: [crop, contain, inside, outside]
|
||||
- name: withoutEnlargement
|
||||
in: query
|
||||
description: No image upscale.
|
||||
schema:
|
||||
type: boolean
|
||||
- name: quality
|
||||
in: query
|
||||
description: Quality of compression.
|
||||
|
||||
Reference in New Issue
Block a user