@uxf/resizer 11.32.0 → 11.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -7
- package/bin/uxf-resizer.js +2 -2
- package/bin/uxf-resizer.ts +1 -1
- package/index.d.ts +2 -5
- package/index.js +4 -140
- package/index.ts +2 -137
- package/package.json +43 -37
- package/src/middleware.d.ts +5 -0
- package/src/middleware.js +115 -0
- package/src/middleware.ts +116 -0
- package/src/next-route.d.ts +2 -0
- package/src/next-route.js +110 -0
- package/src/next-route.ts +107 -0
- package/src/utils/tools.d.ts +10 -0
- package/src/utils/tools.js +45 -0
- package/src/utils/tools.ts +40 -0
- /package/{utils → src/utils}/get-source-filename.d.ts +0 -0
- /package/{utils → src/utils}/get-source-filename.js +0 -0
- /package/{utils → src/utils}/get-source-filename.test.d.ts +0 -0
- /package/{utils → src/utils}/get-source-filename.test.js +0 -0
- /package/{utils → src/utils}/get-source-filename.test.ts +0 -0
- /package/{utils → src/utils}/get-source-filename.ts +0 -0
- /package/{utils → src/utils}/log.d.ts +0 -0
- /package/{utils → src/utils}/log.js +0 -0
- /package/{utils → src/utils}/log.ts +0 -0
- /package/{utils → src/utils}/parse-http-source.d.ts +0 -0
- /package/{utils → src/utils}/parse-http-source.js +0 -0
- /package/{utils → src/utils}/parse-http-source.test.d.ts +0 -0
- /package/{utils → src/utils}/parse-http-source.test.js +0 -0
- /package/{utils → src/utils}/parse-http-source.test.ts +0 -0
- /package/{utils → src/utils}/parse-http-source.ts +0 -0
- /package/{utils → src/utils}/repair-params.d.ts +0 -0
- /package/{utils → src/utils}/repair-params.js +0 -0
- /package/{utils → src/utils}/repair-params.ts +0 -0
package/README.md
CHANGED
|
@@ -2,15 +2,39 @@
|
|
|
2
2
|
[](https://www.npmjs.com/package/@uxf/resizer)
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
## Installation
|
|
5
|
+
## Installation + example (local dev next routes)
|
|
6
6
|
```
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
yarn add @uxf/resizer --dev
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```shell
|
|
11
|
+
src/
|
|
12
|
+
app/
|
|
13
|
+
generated/
|
|
14
|
+
[...path]/
|
|
15
|
+
route.ts # proxy
|
|
16
|
+
static/
|
|
17
|
+
[...path]/
|
|
18
|
+
route.ts # local static files
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
// src/app/generated/[...path]/route.ts
|
|
23
|
+
import { ProxyGET as GET } from "@uxf/resizer";
|
|
11
24
|
|
|
12
|
-
|
|
13
|
-
|
|
25
|
+
export { GET };
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
// src/app/generated/static/[...path]/route.ts
|
|
30
|
+
import { StaticGET as GET } from "@uxf/resizer";
|
|
31
|
+
|
|
32
|
+
export { GET };
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Installation (server)
|
|
36
|
+
```
|
|
37
|
+
yarn add @uxf/resizer express path-to-regexp process yargs
|
|
14
38
|
uxf-resizer
|
|
15
39
|
```
|
|
16
40
|
|
package/bin/uxf-resizer.js
CHANGED
|
@@ -31,7 +31,7 @@ const express_1 = __importDefault(require("express"));
|
|
|
31
31
|
const fs = __importStar(require("fs"));
|
|
32
32
|
const process_1 = require("process");
|
|
33
33
|
const yargs_1 = __importDefault(require("yargs"));
|
|
34
|
-
const
|
|
34
|
+
const middleware_1 = require("../src/middleware");
|
|
35
35
|
const uxfResizer = async () => {
|
|
36
36
|
var _a;
|
|
37
37
|
yargs_1.default.command("$0", "UXF Resizer", (yargs) => {
|
|
@@ -58,7 +58,7 @@ Environment variables:
|
|
|
58
58
|
}
|
|
59
59
|
return new Promise((resolve, reject) => {
|
|
60
60
|
try {
|
|
61
|
-
const app = (0, express_1.default)().use((0,
|
|
61
|
+
const app = (0, express_1.default)().use((0, middleware_1.resizerMiddleware)(config));
|
|
62
62
|
const listenedApp = app.listen(3000, () => {
|
|
63
63
|
// eslint-disable-next-line no-console
|
|
64
64
|
console.log("\nImage resizer app listening on port 3000");
|
package/bin/uxf-resizer.ts
CHANGED
|
@@ -3,7 +3,7 @@ import express from "express";
|
|
|
3
3
|
import * as fs from "fs";
|
|
4
4
|
import { argv, env } from "process";
|
|
5
5
|
import cli from "yargs";
|
|
6
|
-
import { Config, resizerMiddleware } from "../
|
|
6
|
+
import { Config, resizerMiddleware } from "../src/middleware";
|
|
7
7
|
|
|
8
8
|
const uxfResizer = async () => {
|
|
9
9
|
cli.command("$0", "UXF Resizer", (yargs) => {
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,142 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const path_1 = require("path");
|
|
34
|
-
const sharp_1 = __importDefault(require("sharp"));
|
|
35
|
-
const get_source_filename_1 = require("./utils/get-source-filename");
|
|
36
|
-
const log_1 = require("./utils/log");
|
|
37
|
-
const FIT_OPTIONS = {
|
|
38
|
-
cv: "cover",
|
|
39
|
-
f: "fill",
|
|
40
|
-
cn: "contain",
|
|
41
|
-
in: "inside",
|
|
42
|
-
out: "outside",
|
|
43
|
-
};
|
|
44
|
-
const POSITION_OPTIONS = {
|
|
45
|
-
a: "attention",
|
|
46
|
-
b: "bottom",
|
|
47
|
-
c: "centre",
|
|
48
|
-
e: "entropy",
|
|
49
|
-
l: "left",
|
|
50
|
-
lb: "left bottom",
|
|
51
|
-
lt: "left top",
|
|
52
|
-
r: "right",
|
|
53
|
-
rb: "right bottom",
|
|
54
|
-
rt: "right top",
|
|
55
|
-
t: "top",
|
|
56
|
-
};
|
|
57
|
-
const getQuality = ({ quality }) => (quality && quality !== "x" ? Number(quality) : undefined);
|
|
58
|
-
const getWidth = ({ width }) => (width && width !== "x" ? Number(width) : undefined);
|
|
59
|
-
const getHeight = ({ height }) => (height && height !== "x" ? Number(height) : undefined);
|
|
60
|
-
const getBackground = ({ background }) => background === undefined ? undefined : background === "t" ? "transparent" : `#${background}`;
|
|
61
|
-
const getFit = ({ fit }) => { var _a; return (fit ? ((_a = FIT_OPTIONS[fit]) !== null && _a !== void 0 ? _a : "cover") : "cover"); };
|
|
62
|
-
const getPosition = ({ position }) => { var _a; return (position ? ((_a = POSITION_OPTIONS[position]) !== null && _a !== void 0 ? _a : "centre") : undefined); };
|
|
63
|
-
const getWithoutEnlargement = ({ extension }) => extension !== "svg";
|
|
64
|
-
const getTrim = ({ trim }) => (trim === undefined || trim === "nt" ? undefined : Number(trim));
|
|
65
|
-
const resizerMiddleware = (config) => {
|
|
66
|
-
const middleware = (0, express_1.Router)();
|
|
67
|
-
config.forEach((c, i) => {
|
|
68
|
-
(0, log_1.log)(`Config #${i + 1}:`);
|
|
69
|
-
(0, log_1.log)(` Route: ${c.route}`);
|
|
70
|
-
(0, log_1.log)(` Source: ${c.source}`);
|
|
71
|
-
middleware.get(c.route, async (req, res) => {
|
|
72
|
-
var _a;
|
|
73
|
-
(0, log_1.log)("----------------------------------------");
|
|
74
|
-
const params = req.params;
|
|
75
|
-
const generatedFilename = ((_a = process.env.UXF_RESIZER_GENERATE_PATH) !== null && _a !== void 0 ? _a : process.cwd()) + req.path;
|
|
76
|
-
(0, log_1.log)(`Generated filename: ${generatedFilename}`);
|
|
77
|
-
if ((0, fs_1.existsSync)(generatedFilename)) {
|
|
78
|
-
return res.sendFile(generatedFilename);
|
|
79
|
-
}
|
|
80
|
-
const generatedDirectory = (0, path_1.dirname)(generatedFilename);
|
|
81
|
-
if (!(0, fs_1.existsSync)(generatedDirectory)) {
|
|
82
|
-
(0, fs_1.mkdirSync)(generatedDirectory, { recursive: true });
|
|
83
|
-
}
|
|
84
|
-
const sourceFilename = (0, get_source_filename_1.getSourceFilename)(c.source, params);
|
|
85
|
-
(0, log_1.log)(`Source filename: ${sourceFilename}`);
|
|
86
|
-
const sourceFile = /^(http|https)/.test(sourceFilename)
|
|
87
|
-
? await fetch(sourceFilename).then((response) => response.arrayBuffer())
|
|
88
|
-
: sourceFilename;
|
|
89
|
-
if (params.toFormat === "svg") {
|
|
90
|
-
fs.writeFileSync(generatedFilename, sourceFile instanceof ArrayBuffer ? Buffer.from(sourceFile) : sourceFile);
|
|
91
|
-
return res.sendFile(generatedFilename);
|
|
92
|
-
}
|
|
93
|
-
const pipeline = (0, sharp_1.default)(sourceFile)
|
|
94
|
-
.rotate()
|
|
95
|
-
.resize({
|
|
96
|
-
width: getWidth(params),
|
|
97
|
-
height: getHeight(params),
|
|
98
|
-
background: getBackground(params),
|
|
99
|
-
fastShrinkOnLoad: false,
|
|
100
|
-
fit: getFit(params),
|
|
101
|
-
position: getPosition(params),
|
|
102
|
-
withoutEnlargement: getWithoutEnlargement(params),
|
|
103
|
-
});
|
|
104
|
-
const trim = getTrim(params);
|
|
105
|
-
if (trim !== undefined) {
|
|
106
|
-
pipeline.trim({
|
|
107
|
-
threshold: trim,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
const quality = getQuality(params);
|
|
111
|
-
switch (params.toFormat) {
|
|
112
|
-
case "webp":
|
|
113
|
-
pipeline.webp({ quality });
|
|
114
|
-
res.setHeader("Content-Type", "image/webp");
|
|
115
|
-
break;
|
|
116
|
-
case "png":
|
|
117
|
-
pipeline.png({ progressive: true, quality });
|
|
118
|
-
res.setHeader("Content-Type", "image/png");
|
|
119
|
-
break;
|
|
120
|
-
case "avif":
|
|
121
|
-
pipeline.avif({ quality });
|
|
122
|
-
res.setHeader("Content-Type", "image/avif");
|
|
123
|
-
break;
|
|
124
|
-
default:
|
|
125
|
-
pipeline.jpeg({ progressive: true, quality });
|
|
126
|
-
res.setHeader("Content-Type", "image/jpeg");
|
|
127
|
-
break;
|
|
128
|
-
}
|
|
129
|
-
pipeline
|
|
130
|
-
.withMetadata({ density: 72 })
|
|
131
|
-
.toColorspace("srgb")
|
|
132
|
-
.toFile(generatedFilename)
|
|
133
|
-
.then(() => res.sendFile(generatedFilename))
|
|
134
|
-
.catch((e) => {
|
|
135
|
-
(0, log_1.log)(e);
|
|
136
|
-
return res.sendStatus(404);
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
return middleware;
|
|
141
|
-
};
|
|
142
|
-
exports.resizerMiddleware = resizerMiddleware;
|
|
3
|
+
exports.StaticGET = exports.ProxyGET = void 0;
|
|
4
|
+
const next_route_1 = require("./src/next-route");
|
|
5
|
+
Object.defineProperty(exports, "ProxyGET", { enumerable: true, get: function () { return next_route_1.ProxyGET; } });
|
|
6
|
+
Object.defineProperty(exports, "StaticGET", { enumerable: true, get: function () { return next_route_1.StaticGET; } });
|
package/index.ts
CHANGED
|
@@ -1,138 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import * as fs from "fs";
|
|
3
|
-
import { existsSync, mkdirSync } from "fs";
|
|
4
|
-
import { dirname } from "path";
|
|
5
|
-
import sharp, { FitEnum, ResizeOptions } from "sharp";
|
|
6
|
-
import { getSourceFilename } from "./utils/get-source-filename";
|
|
7
|
-
import { log } from "./utils/log";
|
|
1
|
+
import { ProxyGET, StaticGET } from "./src/next-route";
|
|
8
2
|
|
|
9
|
-
|
|
10
|
-
cv: "cover",
|
|
11
|
-
f: "fill",
|
|
12
|
-
cn: "contain",
|
|
13
|
-
in: "inside",
|
|
14
|
-
out: "outside",
|
|
15
|
-
} as const;
|
|
16
|
-
|
|
17
|
-
const POSITION_OPTIONS: Record<string, ResizeOptions["position"]> = {
|
|
18
|
-
a: "attention",
|
|
19
|
-
b: "bottom",
|
|
20
|
-
c: "centre",
|
|
21
|
-
e: "entropy",
|
|
22
|
-
l: "left",
|
|
23
|
-
lb: "left bottom",
|
|
24
|
-
lt: "left top",
|
|
25
|
-
r: "right",
|
|
26
|
-
rb: "right bottom",
|
|
27
|
-
rt: "right top",
|
|
28
|
-
t: "top",
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export type Config = Array<{
|
|
32
|
-
route: string;
|
|
33
|
-
source: string;
|
|
34
|
-
}>;
|
|
35
|
-
|
|
36
|
-
const getQuality = ({ quality }: any) => (quality && quality !== "x" ? Number(quality) : undefined);
|
|
37
|
-
const getWidth = ({ width }: any) => (width && width !== "x" ? Number(width) : undefined);
|
|
38
|
-
const getHeight = ({ height }: any) => (height && height !== "x" ? Number(height) : undefined);
|
|
39
|
-
const getBackground = ({ background }: any) =>
|
|
40
|
-
background === undefined ? undefined : background === "t" ? "transparent" : `#${background}`;
|
|
41
|
-
const getFit = ({ fit }: any): keyof FitEnum => (fit ? (FIT_OPTIONS[fit] ?? "cover") : "cover");
|
|
42
|
-
const getPosition = ({ position }: any) => (position ? (POSITION_OPTIONS[position] ?? "centre") : undefined);
|
|
43
|
-
const getWithoutEnlargement = ({ extension }: any) => extension !== "svg";
|
|
44
|
-
const getTrim = ({ trim }: any) => (trim === undefined || trim === "nt" ? undefined : Number(trim));
|
|
45
|
-
|
|
46
|
-
export const resizerMiddleware = (config: Config) => {
|
|
47
|
-
const middleware = Router();
|
|
48
|
-
|
|
49
|
-
config.forEach((c, i) => {
|
|
50
|
-
log(`Config #${i + 1}:`);
|
|
51
|
-
log(` Route: ${c.route}`);
|
|
52
|
-
log(` Source: ${c.source}`);
|
|
53
|
-
|
|
54
|
-
middleware.get(c.route, async (req, res) => {
|
|
55
|
-
log("----------------------------------------");
|
|
56
|
-
const params = req.params;
|
|
57
|
-
|
|
58
|
-
const generatedFilename = (process.env.UXF_RESIZER_GENERATE_PATH ?? process.cwd()) + req.path;
|
|
59
|
-
log(`Generated filename: ${generatedFilename}`);
|
|
60
|
-
|
|
61
|
-
if (existsSync(generatedFilename)) {
|
|
62
|
-
return res.sendFile(generatedFilename);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const generatedDirectory = dirname(generatedFilename);
|
|
66
|
-
if (!existsSync(generatedDirectory)) {
|
|
67
|
-
mkdirSync(generatedDirectory, { recursive: true });
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const sourceFilename = getSourceFilename(c.source, params);
|
|
71
|
-
log(`Source filename: ${sourceFilename}`);
|
|
72
|
-
|
|
73
|
-
const sourceFile = /^(http|https)/.test(sourceFilename)
|
|
74
|
-
? await fetch(sourceFilename).then((response) => response.arrayBuffer())
|
|
75
|
-
: sourceFilename;
|
|
76
|
-
|
|
77
|
-
if (params.toFormat === "svg") {
|
|
78
|
-
fs.writeFileSync(
|
|
79
|
-
generatedFilename,
|
|
80
|
-
sourceFile instanceof ArrayBuffer ? Buffer.from(sourceFile) : sourceFile,
|
|
81
|
-
);
|
|
82
|
-
return res.sendFile(generatedFilename);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const pipeline = sharp(sourceFile)
|
|
86
|
-
.rotate()
|
|
87
|
-
.resize({
|
|
88
|
-
width: getWidth(params),
|
|
89
|
-
height: getHeight(params),
|
|
90
|
-
background: getBackground(params),
|
|
91
|
-
fastShrinkOnLoad: false,
|
|
92
|
-
fit: getFit(params),
|
|
93
|
-
position: getPosition(params),
|
|
94
|
-
withoutEnlargement: getWithoutEnlargement(params),
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
const trim = getTrim(params);
|
|
98
|
-
if (trim !== undefined) {
|
|
99
|
-
pipeline.trim({
|
|
100
|
-
threshold: trim,
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const quality = getQuality(params);
|
|
105
|
-
|
|
106
|
-
switch (params.toFormat) {
|
|
107
|
-
case "webp":
|
|
108
|
-
pipeline.webp({ quality });
|
|
109
|
-
res.setHeader("Content-Type", "image/webp");
|
|
110
|
-
break;
|
|
111
|
-
case "png":
|
|
112
|
-
pipeline.png({ progressive: true, quality });
|
|
113
|
-
res.setHeader("Content-Type", "image/png");
|
|
114
|
-
break;
|
|
115
|
-
case "avif":
|
|
116
|
-
pipeline.avif({ quality });
|
|
117
|
-
res.setHeader("Content-Type", "image/avif");
|
|
118
|
-
break;
|
|
119
|
-
default:
|
|
120
|
-
pipeline.jpeg({ progressive: true, quality });
|
|
121
|
-
res.setHeader("Content-Type", "image/jpeg");
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
pipeline
|
|
126
|
-
.withMetadata({ density: 72 })
|
|
127
|
-
.toColorspace("srgb")
|
|
128
|
-
.toFile(generatedFilename)
|
|
129
|
-
.then(() => res.sendFile(generatedFilename))
|
|
130
|
-
.catch((e) => {
|
|
131
|
-
log(e);
|
|
132
|
-
return res.sendStatus(404);
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
return middleware;
|
|
138
|
-
};
|
|
3
|
+
export { ProxyGET, StaticGET };
|
package/package.json
CHANGED
|
@@ -1,38 +1,44 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
}
|
|
2
|
+
"name": "@uxf/resizer",
|
|
3
|
+
"version": "11.38.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"description": "UXF Resizer",
|
|
6
|
+
"author": "UXFans <dev@uxf.cz>",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://gitlab.com/uxf-npm/resizer.git"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"uxf-resizer": "bin/uxf-resizer.js"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"sharp": "0.32.6"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/express": "5.0.0",
|
|
23
|
+
"concurrently": "9.0.1",
|
|
24
|
+
"crypto-js": "4.2.0",
|
|
25
|
+
"express": "5.0.1",
|
|
26
|
+
"path-to-regexp": "6.3.0",
|
|
27
|
+
"process": "0.11.10",
|
|
28
|
+
"yargs": "17.7.2"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"express": ">=5.0",
|
|
32
|
+
"path-to-regexp": "^6.3.0",
|
|
33
|
+
"process": ">=0.11",
|
|
34
|
+
"yargs": ">=17.7"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc -P tsconfig.json",
|
|
41
|
+
"dev": "ts-node ./bin/uxf-resizer.ts",
|
|
42
|
+
"typecheck": "tsc --noEmit --skipLibCheck"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.resizerMiddleware = void 0;
|
|
30
|
+
const express_1 = require("express");
|
|
31
|
+
const fs = __importStar(require("fs"));
|
|
32
|
+
const fs_1 = require("fs");
|
|
33
|
+
const path_1 = require("path");
|
|
34
|
+
const sharp_1 = __importDefault(require("sharp"));
|
|
35
|
+
const get_source_filename_1 = require("./utils/get-source-filename");
|
|
36
|
+
const log_1 = require("./utils/log");
|
|
37
|
+
const tools_1 = require("./utils/tools");
|
|
38
|
+
const resizerMiddleware = (config) => {
|
|
39
|
+
const middleware = (0, express_1.Router)();
|
|
40
|
+
config.forEach((c, i) => {
|
|
41
|
+
(0, log_1.log)(`Config #${i + 1}:`);
|
|
42
|
+
(0, log_1.log)(` Route: ${c.route}`);
|
|
43
|
+
(0, log_1.log)(` Source: ${c.source}`);
|
|
44
|
+
middleware.get(c.route, async (req, res) => {
|
|
45
|
+
var _a;
|
|
46
|
+
(0, log_1.log)("----------------------------------------");
|
|
47
|
+
const params = req.params;
|
|
48
|
+
const generatedFilename = ((_a = process.env.UXF_RESIZER_GENERATE_PATH) !== null && _a !== void 0 ? _a : process.cwd()) + req.path;
|
|
49
|
+
(0, log_1.log)(`Generated filename: ${generatedFilename}`);
|
|
50
|
+
if ((0, fs_1.existsSync)(generatedFilename)) {
|
|
51
|
+
return res.sendFile(generatedFilename);
|
|
52
|
+
}
|
|
53
|
+
const generatedDirectory = (0, path_1.dirname)(generatedFilename);
|
|
54
|
+
if (!(0, fs_1.existsSync)(generatedDirectory)) {
|
|
55
|
+
(0, fs_1.mkdirSync)(generatedDirectory, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
const sourceFilename = (0, get_source_filename_1.getSourceFilename)(c.source, params);
|
|
58
|
+
(0, log_1.log)(`Source filename: ${sourceFilename}`);
|
|
59
|
+
const sourceFile = /^(http|https)/.test(sourceFilename)
|
|
60
|
+
? await fetch(sourceFilename).then((response) => response.arrayBuffer())
|
|
61
|
+
: sourceFilename;
|
|
62
|
+
if (params.toFormat === "svg") {
|
|
63
|
+
fs.writeFileSync(generatedFilename, sourceFile instanceof ArrayBuffer ? Buffer.from(sourceFile) : sourceFile);
|
|
64
|
+
return res.sendFile(generatedFilename);
|
|
65
|
+
}
|
|
66
|
+
const pipeline = (0, sharp_1.default)(sourceFile)
|
|
67
|
+
.rotate()
|
|
68
|
+
.resize({
|
|
69
|
+
width: (0, tools_1.getWidth)(params),
|
|
70
|
+
height: (0, tools_1.getHeight)(params),
|
|
71
|
+
background: (0, tools_1.getBackground)(params),
|
|
72
|
+
fastShrinkOnLoad: false,
|
|
73
|
+
fit: (0, tools_1.getFit)(params),
|
|
74
|
+
position: (0, tools_1.getPosition)(params),
|
|
75
|
+
withoutEnlargement: (0, tools_1.getWithoutEnlargement)(params),
|
|
76
|
+
});
|
|
77
|
+
const trim = (0, tools_1.getTrim)(params);
|
|
78
|
+
if (trim !== undefined) {
|
|
79
|
+
pipeline.trim({
|
|
80
|
+
threshold: trim,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
const quality = (0, tools_1.getQuality)(params);
|
|
84
|
+
switch (params.toFormat) {
|
|
85
|
+
case "webp":
|
|
86
|
+
pipeline.webp({ quality });
|
|
87
|
+
res.setHeader("Content-Type", "image/webp");
|
|
88
|
+
break;
|
|
89
|
+
case "png":
|
|
90
|
+
pipeline.png({ progressive: true, quality });
|
|
91
|
+
res.setHeader("Content-Type", "image/png");
|
|
92
|
+
break;
|
|
93
|
+
case "avif":
|
|
94
|
+
pipeline.avif({ quality });
|
|
95
|
+
res.setHeader("Content-Type", "image/avif");
|
|
96
|
+
break;
|
|
97
|
+
default:
|
|
98
|
+
pipeline.jpeg({ progressive: true, quality });
|
|
99
|
+
res.setHeader("Content-Type", "image/jpeg");
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
pipeline
|
|
103
|
+
.withMetadata({ density: 72 })
|
|
104
|
+
.toColorspace("srgb")
|
|
105
|
+
.toFile(generatedFilename)
|
|
106
|
+
.then(() => res.sendFile(generatedFilename))
|
|
107
|
+
.catch((e) => {
|
|
108
|
+
(0, log_1.log)(e);
|
|
109
|
+
return res.sendStatus(404);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
return middleware;
|
|
114
|
+
};
|
|
115
|
+
exports.resizerMiddleware = resizerMiddleware;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import { existsSync, mkdirSync } from "fs";
|
|
4
|
+
import { dirname } from "path";
|
|
5
|
+
import sharp from "sharp";
|
|
6
|
+
import { getSourceFilename } from "./utils/get-source-filename";
|
|
7
|
+
import { log } from "./utils/log";
|
|
8
|
+
import {
|
|
9
|
+
getBackground,
|
|
10
|
+
getFit,
|
|
11
|
+
getHeight,
|
|
12
|
+
getPosition,
|
|
13
|
+
getQuality,
|
|
14
|
+
getTrim,
|
|
15
|
+
getWidth,
|
|
16
|
+
getWithoutEnlargement,
|
|
17
|
+
} from "./utils/tools";
|
|
18
|
+
|
|
19
|
+
export type Config = Array<{
|
|
20
|
+
route: string;
|
|
21
|
+
source: string;
|
|
22
|
+
}>;
|
|
23
|
+
|
|
24
|
+
export const resizerMiddleware = (config: Config) => {
|
|
25
|
+
const middleware = Router();
|
|
26
|
+
|
|
27
|
+
config.forEach((c, i) => {
|
|
28
|
+
log(`Config #${i + 1}:`);
|
|
29
|
+
log(` Route: ${c.route}`);
|
|
30
|
+
log(` Source: ${c.source}`);
|
|
31
|
+
|
|
32
|
+
middleware.get(c.route, async (req, res) => {
|
|
33
|
+
log("----------------------------------------");
|
|
34
|
+
const params = req.params;
|
|
35
|
+
|
|
36
|
+
const generatedFilename = (process.env.UXF_RESIZER_GENERATE_PATH ?? process.cwd()) + req.path;
|
|
37
|
+
log(`Generated filename: ${generatedFilename}`);
|
|
38
|
+
|
|
39
|
+
if (existsSync(generatedFilename)) {
|
|
40
|
+
return res.sendFile(generatedFilename);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const generatedDirectory = dirname(generatedFilename);
|
|
44
|
+
if (!existsSync(generatedDirectory)) {
|
|
45
|
+
mkdirSync(generatedDirectory, { recursive: true });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const sourceFilename = getSourceFilename(c.source, params);
|
|
49
|
+
log(`Source filename: ${sourceFilename}`);
|
|
50
|
+
|
|
51
|
+
const sourceFile = /^(http|https)/.test(sourceFilename)
|
|
52
|
+
? await fetch(sourceFilename).then((response) => response.arrayBuffer())
|
|
53
|
+
: sourceFilename;
|
|
54
|
+
|
|
55
|
+
if (params.toFormat === "svg") {
|
|
56
|
+
fs.writeFileSync(
|
|
57
|
+
generatedFilename,
|
|
58
|
+
sourceFile instanceof ArrayBuffer ? Buffer.from(sourceFile) : sourceFile,
|
|
59
|
+
);
|
|
60
|
+
return res.sendFile(generatedFilename);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const pipeline = sharp(sourceFile)
|
|
64
|
+
.rotate()
|
|
65
|
+
.resize({
|
|
66
|
+
width: getWidth(params),
|
|
67
|
+
height: getHeight(params),
|
|
68
|
+
background: getBackground(params),
|
|
69
|
+
fastShrinkOnLoad: false,
|
|
70
|
+
fit: getFit(params),
|
|
71
|
+
position: getPosition(params),
|
|
72
|
+
withoutEnlargement: getWithoutEnlargement(params),
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const trim = getTrim(params);
|
|
76
|
+
if (trim !== undefined) {
|
|
77
|
+
pipeline.trim({
|
|
78
|
+
threshold: trim,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const quality = getQuality(params);
|
|
83
|
+
|
|
84
|
+
switch (params.toFormat) {
|
|
85
|
+
case "webp":
|
|
86
|
+
pipeline.webp({ quality });
|
|
87
|
+
res.setHeader("Content-Type", "image/webp");
|
|
88
|
+
break;
|
|
89
|
+
case "png":
|
|
90
|
+
pipeline.png({ progressive: true, quality });
|
|
91
|
+
res.setHeader("Content-Type", "image/png");
|
|
92
|
+
break;
|
|
93
|
+
case "avif":
|
|
94
|
+
pipeline.avif({ quality });
|
|
95
|
+
res.setHeader("Content-Type", "image/avif");
|
|
96
|
+
break;
|
|
97
|
+
default:
|
|
98
|
+
pipeline.jpeg({ progressive: true, quality });
|
|
99
|
+
res.setHeader("Content-Type", "image/jpeg");
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
pipeline
|
|
104
|
+
.withMetadata({ density: 72 })
|
|
105
|
+
.toColorspace("srgb")
|
|
106
|
+
.toFile(generatedFilename)
|
|
107
|
+
.then(() => res.sendFile(generatedFilename))
|
|
108
|
+
.catch((e) => {
|
|
109
|
+
log(e);
|
|
110
|
+
return res.sendStatus(404);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return middleware;
|
|
116
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.StaticGET = StaticGET;
|
|
30
|
+
exports.ProxyGET = ProxyGET;
|
|
31
|
+
const fs_1 = __importStar(require("fs"));
|
|
32
|
+
const path_1 = require("path");
|
|
33
|
+
const sharp_1 = __importDefault(require("sharp"));
|
|
34
|
+
const log_1 = require("./utils/log");
|
|
35
|
+
const tools_1 = require("./utils/tools");
|
|
36
|
+
const sendFile = (generatedFilename, contentType) => {
|
|
37
|
+
const data = fs_1.default.readFileSync(generatedFilename);
|
|
38
|
+
return new Response(data, {
|
|
39
|
+
headers: {
|
|
40
|
+
"Content-Type": contentType,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
// lokalni zpracovani obrazku
|
|
45
|
+
async function StaticGET(request) {
|
|
46
|
+
var _a, _b;
|
|
47
|
+
const url = new URL(request.url);
|
|
48
|
+
const path = url.pathname;
|
|
49
|
+
const regex = /^\/generated\/static\/(?<width>\d+|x)_(?<height>\d+|x)_(?<fit>[a-z]+)_(?<position>[a-z]+)_(?<background>[0-9a-f]+)_(?<trim>[a-z]+)_(?<quality>\d+|x)\/(?<version>[a-z0-9]+)\/(?<filename>.+)\.(?<extension>[a-z]+)\.(?<toFormat>[a-z]+)/i;
|
|
50
|
+
const params = (_a = path.match(regex)) === null || _a === void 0 ? void 0 : _a.groups;
|
|
51
|
+
if (params === undefined) {
|
|
52
|
+
return Response.error();
|
|
53
|
+
}
|
|
54
|
+
const generatedFilename = process.cwd() + path;
|
|
55
|
+
(0, log_1.log)(`Generated filename: ${generatedFilename}`);
|
|
56
|
+
const contentType = (_b = tools_1.CONTENT_TYPES[params.toFormat]) !== null && _b !== void 0 ? _b : "image/jpeg";
|
|
57
|
+
if ((0, fs_1.existsSync)(generatedFilename)) {
|
|
58
|
+
return sendFile(generatedFilename, contentType);
|
|
59
|
+
}
|
|
60
|
+
const generatedDirectory = (0, path_1.dirname)(generatedFilename);
|
|
61
|
+
if (!(0, fs_1.existsSync)(generatedDirectory)) {
|
|
62
|
+
(0, fs_1.mkdirSync)(generatedDirectory, { recursive: true });
|
|
63
|
+
}
|
|
64
|
+
const sourceFile = process.cwd() + `/public/${params.filename}.${params.extension}`;
|
|
65
|
+
(0, log_1.log)(`Source filename: ${sourceFile}`);
|
|
66
|
+
if (params.toFormat === "svg") {
|
|
67
|
+
fs_1.default.writeFileSync(generatedFilename, sourceFile);
|
|
68
|
+
return sendFile(generatedFilename, "image/svg+xml");
|
|
69
|
+
}
|
|
70
|
+
const pipeline = (0, sharp_1.default)(sourceFile)
|
|
71
|
+
.rotate()
|
|
72
|
+
.resize({
|
|
73
|
+
width: (0, tools_1.getWidth)(params),
|
|
74
|
+
height: (0, tools_1.getHeight)(params),
|
|
75
|
+
background: (0, tools_1.getBackground)(params),
|
|
76
|
+
fastShrinkOnLoad: false,
|
|
77
|
+
fit: (0, tools_1.getFit)(params),
|
|
78
|
+
position: (0, tools_1.getPosition)(params),
|
|
79
|
+
withoutEnlargement: (0, tools_1.getWithoutEnlargement)(params),
|
|
80
|
+
});
|
|
81
|
+
const trim = (0, tools_1.getTrim)(params);
|
|
82
|
+
if (trim !== undefined) {
|
|
83
|
+
pipeline.trim({
|
|
84
|
+
threshold: trim,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const quality = (0, tools_1.getQuality)(params);
|
|
88
|
+
switch (params.toFormat) {
|
|
89
|
+
case "webp":
|
|
90
|
+
pipeline.webp({ quality });
|
|
91
|
+
break;
|
|
92
|
+
case "png":
|
|
93
|
+
pipeline.png({ progressive: true, quality });
|
|
94
|
+
break;
|
|
95
|
+
case "avif":
|
|
96
|
+
pipeline.avif({ quality });
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
pipeline.jpeg({ progressive: true, quality });
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
await pipeline.withMetadata({ density: 72 }).toColorspace("srgb").toFile(generatedFilename);
|
|
103
|
+
return sendFile(generatedFilename, contentType);
|
|
104
|
+
}
|
|
105
|
+
// proxy na dev
|
|
106
|
+
async function ProxyGET(request) {
|
|
107
|
+
const url = new URL(request.url);
|
|
108
|
+
const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}${url.pathname}`);
|
|
109
|
+
return new Response(response.body);
|
|
110
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import fs, { existsSync, mkdirSync } from "fs";
|
|
2
|
+
import { dirname } from "path";
|
|
3
|
+
import sharp from "sharp";
|
|
4
|
+
import { log } from "./utils/log";
|
|
5
|
+
import {
|
|
6
|
+
CONTENT_TYPES,
|
|
7
|
+
getBackground,
|
|
8
|
+
getFit,
|
|
9
|
+
getHeight,
|
|
10
|
+
getPosition,
|
|
11
|
+
getQuality,
|
|
12
|
+
getTrim,
|
|
13
|
+
getWidth,
|
|
14
|
+
getWithoutEnlargement,
|
|
15
|
+
} from "./utils/tools";
|
|
16
|
+
|
|
17
|
+
const sendFile = (generatedFilename: string, contentType: string) => {
|
|
18
|
+
const data = fs.readFileSync(generatedFilename);
|
|
19
|
+
return new Response(data, {
|
|
20
|
+
headers: {
|
|
21
|
+
"Content-Type": contentType,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// lokalni zpracovani obrazku
|
|
27
|
+
export async function StaticGET(request: Request) {
|
|
28
|
+
const url = new URL(request.url);
|
|
29
|
+
const path = url.pathname;
|
|
30
|
+
|
|
31
|
+
const regex =
|
|
32
|
+
/^\/generated\/static\/(?<width>\d+|x)_(?<height>\d+|x)_(?<fit>[a-z]+)_(?<position>[a-z]+)_(?<background>[0-9a-f]+)_(?<trim>[a-z]+)_(?<quality>\d+|x)\/(?<version>[a-z0-9]+)\/(?<filename>.+)\.(?<extension>[a-z]+)\.(?<toFormat>[a-z]+)/i;
|
|
33
|
+
|
|
34
|
+
const params = path.match(regex)?.groups;
|
|
35
|
+
if (params === undefined) {
|
|
36
|
+
return Response.error();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const generatedFilename = process.cwd() + path;
|
|
40
|
+
log(`Generated filename: ${generatedFilename}`);
|
|
41
|
+
|
|
42
|
+
const contentType = CONTENT_TYPES[params.toFormat] ?? "image/jpeg";
|
|
43
|
+
|
|
44
|
+
if (existsSync(generatedFilename)) {
|
|
45
|
+
return sendFile(generatedFilename, contentType);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const generatedDirectory = dirname(generatedFilename);
|
|
49
|
+
if (!existsSync(generatedDirectory)) {
|
|
50
|
+
mkdirSync(generatedDirectory, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const sourceFile = process.cwd() + `/public/${params.filename}.${params.extension}`;
|
|
54
|
+
log(`Source filename: ${sourceFile}`);
|
|
55
|
+
|
|
56
|
+
if (params.toFormat === "svg") {
|
|
57
|
+
fs.writeFileSync(generatedFilename, sourceFile);
|
|
58
|
+
return sendFile(generatedFilename, "image/svg+xml");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const pipeline = sharp(sourceFile)
|
|
62
|
+
.rotate()
|
|
63
|
+
.resize({
|
|
64
|
+
width: getWidth(params),
|
|
65
|
+
height: getHeight(params),
|
|
66
|
+
background: getBackground(params),
|
|
67
|
+
fastShrinkOnLoad: false,
|
|
68
|
+
fit: getFit(params),
|
|
69
|
+
position: getPosition(params),
|
|
70
|
+
withoutEnlargement: getWithoutEnlargement(params),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const trim = getTrim(params);
|
|
74
|
+
if (trim !== undefined) {
|
|
75
|
+
pipeline.trim({
|
|
76
|
+
threshold: trim,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const quality = getQuality(params);
|
|
81
|
+
|
|
82
|
+
switch (params.toFormat) {
|
|
83
|
+
case "webp":
|
|
84
|
+
pipeline.webp({ quality });
|
|
85
|
+
break;
|
|
86
|
+
case "png":
|
|
87
|
+
pipeline.png({ progressive: true, quality });
|
|
88
|
+
break;
|
|
89
|
+
case "avif":
|
|
90
|
+
pipeline.avif({ quality });
|
|
91
|
+
break;
|
|
92
|
+
default:
|
|
93
|
+
pipeline.jpeg({ progressive: true, quality });
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
await pipeline.withMetadata({ density: 72 }).toColorspace("srgb").toFile(generatedFilename);
|
|
98
|
+
|
|
99
|
+
return sendFile(generatedFilename, contentType);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// proxy na dev
|
|
103
|
+
export async function ProxyGET(request: Request) {
|
|
104
|
+
const url = new URL(request.url);
|
|
105
|
+
const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}${url.pathname}`);
|
|
106
|
+
return new Response(response.body);
|
|
107
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FitEnum } from "sharp";
|
|
2
|
+
export declare const CONTENT_TYPES: Record<string, string | undefined>;
|
|
3
|
+
export declare const getQuality: ({ quality }: any) => number | undefined;
|
|
4
|
+
export declare const getWidth: ({ width }: any) => number | undefined;
|
|
5
|
+
export declare const getHeight: ({ height }: any) => number | undefined;
|
|
6
|
+
export declare const getBackground: ({ background }: any) => string | undefined;
|
|
7
|
+
export declare const getFit: ({ fit }: any) => keyof FitEnum;
|
|
8
|
+
export declare const getPosition: ({ position }: any) => string | number | undefined;
|
|
9
|
+
export declare const getWithoutEnlargement: ({ extension }: any) => boolean;
|
|
10
|
+
export declare const getTrim: ({ trim }: any) => number | undefined;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTrim = exports.getWithoutEnlargement = exports.getPosition = exports.getFit = exports.getBackground = exports.getHeight = exports.getWidth = exports.getQuality = exports.CONTENT_TYPES = void 0;
|
|
4
|
+
const FIT_OPTIONS = {
|
|
5
|
+
cv: "cover",
|
|
6
|
+
f: "fill",
|
|
7
|
+
cn: "contain",
|
|
8
|
+
in: "inside",
|
|
9
|
+
out: "outside",
|
|
10
|
+
};
|
|
11
|
+
const POSITION_OPTIONS = {
|
|
12
|
+
a: "attention",
|
|
13
|
+
b: "bottom",
|
|
14
|
+
c: "centre",
|
|
15
|
+
e: "entropy",
|
|
16
|
+
l: "left",
|
|
17
|
+
lb: "left bottom",
|
|
18
|
+
lt: "left top",
|
|
19
|
+
r: "right",
|
|
20
|
+
rb: "right bottom",
|
|
21
|
+
rt: "right top",
|
|
22
|
+
t: "top",
|
|
23
|
+
};
|
|
24
|
+
exports.CONTENT_TYPES = {
|
|
25
|
+
webp: "image/webp",
|
|
26
|
+
png: "image/png",
|
|
27
|
+
avif: "image/avif",
|
|
28
|
+
jpeg: "image/jpeg",
|
|
29
|
+
};
|
|
30
|
+
const getQuality = ({ quality }) => (quality && quality !== "x" ? Number(quality) : undefined);
|
|
31
|
+
exports.getQuality = getQuality;
|
|
32
|
+
const getWidth = ({ width }) => (width && width !== "x" ? Number(width) : undefined);
|
|
33
|
+
exports.getWidth = getWidth;
|
|
34
|
+
const getHeight = ({ height }) => (height && height !== "x" ? Number(height) : undefined);
|
|
35
|
+
exports.getHeight = getHeight;
|
|
36
|
+
const getBackground = ({ background }) => background === undefined ? undefined : background === "t" ? "transparent" : `#${background}`;
|
|
37
|
+
exports.getBackground = getBackground;
|
|
38
|
+
const getFit = ({ fit }) => { var _a; return (fit ? ((_a = FIT_OPTIONS[fit]) !== null && _a !== void 0 ? _a : "cover") : "cover"); };
|
|
39
|
+
exports.getFit = getFit;
|
|
40
|
+
const getPosition = ({ position }) => { var _a; return (position ? ((_a = POSITION_OPTIONS[position]) !== null && _a !== void 0 ? _a : "centre") : undefined); };
|
|
41
|
+
exports.getPosition = getPosition;
|
|
42
|
+
const getWithoutEnlargement = ({ extension }) => extension !== "svg";
|
|
43
|
+
exports.getWithoutEnlargement = getWithoutEnlargement;
|
|
44
|
+
const getTrim = ({ trim }) => (trim === undefined || trim === "nt" ? undefined : Number(trim));
|
|
45
|
+
exports.getTrim = getTrim;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { FitEnum, ResizeOptions } from "sharp";
|
|
2
|
+
|
|
3
|
+
const FIT_OPTIONS: Record<string, ResizeOptions["fit"]> = {
|
|
4
|
+
cv: "cover",
|
|
5
|
+
f: "fill",
|
|
6
|
+
cn: "contain",
|
|
7
|
+
in: "inside",
|
|
8
|
+
out: "outside",
|
|
9
|
+
} as const;
|
|
10
|
+
|
|
11
|
+
const POSITION_OPTIONS: Record<string, ResizeOptions["position"]> = {
|
|
12
|
+
a: "attention",
|
|
13
|
+
b: "bottom",
|
|
14
|
+
c: "centre",
|
|
15
|
+
e: "entropy",
|
|
16
|
+
l: "left",
|
|
17
|
+
lb: "left bottom",
|
|
18
|
+
lt: "left top",
|
|
19
|
+
r: "right",
|
|
20
|
+
rb: "right bottom",
|
|
21
|
+
rt: "right top",
|
|
22
|
+
t: "top",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const CONTENT_TYPES: Record<string, string | undefined> = {
|
|
26
|
+
webp: "image/webp",
|
|
27
|
+
png: "image/png",
|
|
28
|
+
avif: "image/avif",
|
|
29
|
+
jpeg: "image/jpeg",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const getQuality = ({ quality }: any) => (quality && quality !== "x" ? Number(quality) : undefined);
|
|
33
|
+
export const getWidth = ({ width }: any) => (width && width !== "x" ? Number(width) : undefined);
|
|
34
|
+
export const getHeight = ({ height }: any) => (height && height !== "x" ? Number(height) : undefined);
|
|
35
|
+
export const getBackground = ({ background }: any) =>
|
|
36
|
+
background === undefined ? undefined : background === "t" ? "transparent" : `#${background}`;
|
|
37
|
+
export const getFit = ({ fit }: any): keyof FitEnum => (fit ? (FIT_OPTIONS[fit] ?? "cover") : "cover");
|
|
38
|
+
export const getPosition = ({ position }: any) => (position ? (POSITION_OPTIONS[position] ?? "centre") : undefined);
|
|
39
|
+
export const getWithoutEnlargement = ({ extension }: any) => extension !== "svg";
|
|
40
|
+
export const getTrim = ({ trim }: any) => (trim === undefined || trim === "nt" ? undefined : Number(trim));
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|