@imagekit/javascript 5.0.0-beta.7 → 5.1.0-beta.1

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/src/url.ts DELETED
@@ -1,301 +0,0 @@
1
- import { SrcOptions } from "./interfaces";
2
- import { ImageOverlay, SolidColorOverlay, SubtitleOverlay, TextOverlay, Transformation, VideoOverlay } from "./interfaces/Transformation";
3
- import transformationUtils, { safeBtoa } from "./utils/transformation";
4
- const TRANSFORMATION_PARAMETER = "tr";
5
- const SIMPLE_OVERLAY_PATH_REGEX = new RegExp('^[a-zA-Z0-9-._/ ]*$')
6
- const SIMPLE_OVERLAY_TEXT_REGEX = new RegExp('^[a-zA-Z0-9-._ ]*$') // These characters are selected by testing actual URLs on both path and query parameters. If and when backend starts supporting wide range of characters, this regex should be updated to improve URL readability.
7
-
8
- function removeTrailingSlash(str: string) {
9
- if (typeof str == "string" && str[str.length - 1] == "/") {
10
- str = str.substring(0, str.length - 1);
11
- }
12
- return str;
13
- }
14
-
15
- function removeLeadingSlash(str: string) {
16
- if (typeof str == "string" && str[0] == "/") {
17
- str = str.slice(1);
18
- }
19
- return str;
20
- }
21
-
22
- function pathJoin(parts: string[], sep?: string) {
23
- var separator = sep || "/";
24
- var replace = new RegExp(separator + "{1,}", "g");
25
- return parts.join(separator).replace(replace, separator);
26
- }
27
-
28
- /**
29
- * Builds a source URL with the given options.
30
- *
31
- * @param {SrcOptions} opts - The options for building the source URL.
32
- * @returns {string} The constructed source URL.
33
- */
34
- export const buildSrc = (opts: SrcOptions): string => {
35
- opts.urlEndpoint = opts.urlEndpoint || "";
36
- opts.src = opts.src || "";
37
- opts.transformationPosition = opts.transformationPosition || "query";
38
-
39
- if (!opts.src) {
40
- return "";
41
- }
42
-
43
- const isAbsoluteURL = opts.src.startsWith("http://") || opts.src.startsWith("https://");
44
-
45
- var urlObj, isSrcParameterUsedForURL, urlEndpointPattern;
46
-
47
- try {
48
- if (!isAbsoluteURL) {
49
- urlEndpointPattern = new URL(opts.urlEndpoint).pathname;
50
- urlObj = new URL(pathJoin([opts.urlEndpoint.replace(urlEndpointPattern, ""), opts.src]));
51
- } else {
52
- urlObj = new URL(opts.src!);
53
- isSrcParameterUsedForURL = true;
54
- }
55
- } catch (e) {
56
- console.error(e)
57
- return "";
58
- }
59
-
60
- for (var i in opts.queryParameters) {
61
- urlObj.searchParams.append(i, String(opts.queryParameters[i]));
62
- }
63
-
64
- var transformationString = buildTransformationString(opts.transformation);
65
-
66
- if (transformationString && transformationString.length) {
67
- if (!transformationUtils.addAsQueryParameter(opts) && !isSrcParameterUsedForURL) {
68
- urlObj.pathname = pathJoin([
69
- TRANSFORMATION_PARAMETER + transformationUtils.getChainTransformDelimiter() + transformationString,
70
- urlObj.pathname,
71
- ]);
72
- }
73
- }
74
-
75
- if (urlEndpointPattern) {
76
- urlObj.pathname = pathJoin([urlEndpointPattern, urlObj.pathname]);
77
- } else {
78
- urlObj.pathname = pathJoin([urlObj.pathname]);
79
- }
80
-
81
- if (transformationString && transformationString.length) {
82
- if (transformationUtils.addAsQueryParameter(opts) || isSrcParameterUsedForURL) {
83
- if (urlObj.searchParams.toString() !== "") { // In 12 node.js .size was not there. So, we need to check if it is an object or not.
84
- return `${urlObj.href}&${TRANSFORMATION_PARAMETER}=${transformationString}`;
85
- }
86
- else {
87
- return `${urlObj.href}?${TRANSFORMATION_PARAMETER}=${transformationString}`;
88
- }
89
- }
90
- }
91
-
92
- return urlObj.href;
93
- };
94
-
95
- function processInputPath(str: string, enccoding: string): string {
96
- // Remove leading and trailing slashes
97
- str = removeTrailingSlash(removeLeadingSlash(str));
98
- if (enccoding === "plain") {
99
- return `i-${str.replace(/\//g, "@@")}`;
100
- }
101
- if (enccoding === "base64") {
102
- return `ie-${encodeURIComponent(safeBtoa(str))}`;
103
- }
104
- if (SIMPLE_OVERLAY_PATH_REGEX.test(str)) {
105
- return `i-${str.replace(/\//g, "@@")}`;
106
- } else {
107
- return `ie-${encodeURIComponent(safeBtoa(str))}`;
108
- }
109
- }
110
-
111
- function processText(str: string, enccoding: TextOverlay["encoding"]): string {
112
- if (enccoding === "plain") {
113
- return `i-${encodeURIComponent(str)}`;
114
- }
115
- if (enccoding === "base64") {
116
- return `ie-${encodeURIComponent(safeBtoa(str))}`;
117
- }
118
- if (SIMPLE_OVERLAY_TEXT_REGEX.test(str)) {
119
- return `i-${encodeURIComponent(str)}`;
120
- }
121
- return `ie-${encodeURIComponent(safeBtoa(str))}`;
122
- }
123
-
124
- function processOverlay(overlay: Transformation["overlay"]): string | undefined {
125
- const entries = [];
126
-
127
- const { type, position = {}, timing = {}, transformation = [] } = overlay || {};
128
-
129
- if (!type) {
130
- return;
131
- }
132
-
133
- switch (type) {
134
- case "text": {
135
- const textOverlay = overlay as TextOverlay;
136
- if (!textOverlay.text) {
137
- return;
138
- }
139
- const enccoding = textOverlay.encoding || "auto";
140
-
141
- entries.push("l-text");
142
- entries.push(processText(textOverlay.text, enccoding));
143
- }
144
- break;
145
- case "image":
146
- entries.push("l-image");
147
- {
148
- const imageOverlay = overlay as ImageOverlay;
149
- const enccoding = imageOverlay.encoding || "auto";
150
- if (imageOverlay.input) {
151
- entries.push(processInputPath(imageOverlay.input, enccoding));
152
- } else {
153
- return;
154
- }
155
- }
156
- break;
157
- case "video":
158
- entries.push("l-video");
159
- {
160
- const videoOverlay = overlay as VideoOverlay;
161
- const enccoding = videoOverlay.encoding || "auto";
162
- if (videoOverlay.input) {
163
- entries.push(processInputPath(videoOverlay.input, enccoding));
164
- } else {
165
- return;
166
- }
167
- }
168
- break;
169
- case "subtitle":
170
- entries.push("l-subtitle");
171
- {
172
- const subtitleOverlay = overlay as SubtitleOverlay;
173
- const enccoding = subtitleOverlay.encoding || "auto";
174
- if (subtitleOverlay.input) {
175
- entries.push(processInputPath(subtitleOverlay.input, enccoding));
176
- } else {
177
- return;
178
- }
179
- }
180
- break;
181
- case "solidColor":
182
- entries.push("l-image");
183
- entries.push(`i-ik_canvas`);
184
- {
185
- const solidColorOverlay = overlay as SolidColorOverlay;
186
- if (solidColorOverlay.color) {
187
- entries.push(`bg-${solidColorOverlay.color}`);
188
- } else {
189
- return;
190
- }
191
- }
192
- break;
193
- }
194
-
195
- const { x, y, focus } = position;
196
- if (x) {
197
- entries.push(`lx-${x}`);
198
- }
199
- if (y) {
200
- entries.push(`ly-${y}`);
201
- }
202
- if (focus) {
203
- entries.push(`lfo-${focus}`);
204
- }
205
-
206
- const { start, end, duration } = timing;
207
-
208
- if (start) {
209
- entries.push(`lso-${start}`);
210
- }
211
- if (end) {
212
- entries.push(`leo-${end}`);
213
- }
214
- if (duration) {
215
- entries.push(`ldu-${duration}`);
216
- }
217
-
218
- const transformationString = buildTransformationString(transformation);
219
-
220
- if (transformationString && transformationString.trim() !== "") entries.push(transformationString);
221
-
222
- entries.push("l-end");
223
-
224
- return entries.join(transformationUtils.getTransformDelimiter());
225
- }
226
-
227
- /**
228
- * Builds a transformation string from the given transformations.
229
- *
230
- * @param {Transformation[] | undefined} transformation - The transformations to apply.
231
- * @returns {string} The constructed transformation string.
232
- */
233
- export const buildTransformationString = function (transformation: Transformation[] | undefined): string {
234
- if (!Array.isArray(transformation)) {
235
- return "";
236
- }
237
-
238
- var parsedTransforms: string[] = [];
239
- for (var i = 0, l = transformation.length; i < l; i++) {
240
- var parsedTransformStep: string[] = [];
241
- for (var key in transformation[i]) {
242
- let value = transformation[i][key as keyof Transformation];
243
- if (value === undefined || value === null) {
244
- continue;
245
- }
246
-
247
- if (key === "overlay" && typeof value === "object") {
248
- var rawString = processOverlay(value as Transformation["overlay"]);
249
- if (rawString && rawString.trim() !== "") {
250
- parsedTransformStep.push(rawString);
251
- }
252
- continue; // Always continue as overlay is processed.
253
- }
254
-
255
- var transformKey = transformationUtils.getTransformKey(key);
256
- if (!transformKey) {
257
- transformKey = key;
258
- }
259
-
260
- if (transformKey === "") {
261
- continue;
262
- }
263
-
264
- if (
265
- ["e-grayscale", "e-contrast", "e-removedotbg", "e-bgremove", "e-upscale", "e-retouch", "e-genvar"].includes(transformKey)
266
- ) {
267
- if (value === true || value === "-" || value === "true") {
268
- parsedTransformStep.push(transformKey);
269
- } else {
270
- // Any other value means that the effect should not be applied
271
- continue;
272
- }
273
- } else if (
274
- ["e-sharpen", "e-shadow", "e-gradient", "e-usm", "e-dropshadow"].includes(transformKey) &&
275
- (value.toString().trim() === "" || value === true || value === "true")
276
- ) {
277
- parsedTransformStep.push(transformKey);
278
- } else if (key === "raw") {
279
- parsedTransformStep.push(transformation[i][key] as string);
280
- } else {
281
- if (transformKey === "di") {
282
- value = removeTrailingSlash(removeLeadingSlash(value as string || ""));
283
- value = value.replace(/\//g, "@@");
284
- }
285
- if (transformKey === "sr" && Array.isArray(value)) {
286
- value = value.join("_");
287
- }
288
- // Special case for trim with empty string - should be treated as true
289
- if (transformKey === "t" && value.toString().trim() === "") {
290
- value = "true";
291
- }
292
- parsedTransformStep.push([transformKey, value].join(transformationUtils.getTransformKeyValueDelimiter()));
293
- }
294
- }
295
- if (parsedTransformStep.length) {
296
- parsedTransforms.push(parsedTransformStep.join(transformationUtils.getTransformDelimiter()));
297
- }
298
- }
299
-
300
- return parsedTransforms.join(transformationUtils.getChainTransformDelimiter());
301
- }
@@ -1,40 +0,0 @@
1
- import supportedTransforms from "../constants/supportedTransforms";
2
- import { TransformationPosition, SrcOptions } from "../interfaces";
3
-
4
- const QUERY_TRANSFORMATION_POSITION: TransformationPosition = "query";
5
- const PATH_TRANSFORMATION_POSITION: TransformationPosition = "path";
6
- const DEFAULT_TRANSFORMATION_POSITION: TransformationPosition = QUERY_TRANSFORMATION_POSITION;
7
- const VALID_TRANSFORMATION_POSITIONS = [PATH_TRANSFORMATION_POSITION, QUERY_TRANSFORMATION_POSITION];
8
- const CHAIN_TRANSFORM_DELIMITER: string = ":";
9
- const TRANSFORM_DELIMITER: string = ",";
10
- const TRANSFORM_KEY_VALUE_DELIMITER: string = "-";
11
-
12
- export default {
13
- addAsQueryParameter: (options: SrcOptions) => {
14
- return options.transformationPosition === QUERY_TRANSFORMATION_POSITION;
15
- },
16
- getTransformKey: function (transform: string) {
17
- if (!transform) { return ""; }
18
-
19
- return supportedTransforms[transform] || supportedTransforms[transform.toLowerCase()] || "";
20
- },
21
- getChainTransformDelimiter: function () {
22
- return CHAIN_TRANSFORM_DELIMITER;
23
- },
24
- getTransformDelimiter: function () {
25
- return TRANSFORM_DELIMITER;
26
- },
27
- getTransformKeyValueDelimiter: function () {
28
- return TRANSFORM_KEY_VALUE_DELIMITER;
29
- }
30
- }
31
-
32
- export const safeBtoa = function (str: string): string {
33
- if (typeof window !== "undefined") {
34
- /* istanbul ignore next */
35
- return btoa(str);
36
- } else {
37
- // Node fallback
38
- return Buffer.from(str, "utf8").toString("base64");
39
- }
40
- }