@giphy/js-util 0.0.0-canary-20230620165510

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/dist/index.js ADDED
@@ -0,0 +1,320 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+
21
+ // src/log.ts
22
+ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
23
+ LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
24
+ LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
25
+ LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
26
+ LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
27
+ return LogLevel2;
28
+ })(LogLevel || {});
29
+ var Logger = {
30
+ ENABLED: typeof window !== "undefined" && typeof location !== "undefined" && location.search.indexOf("giphy-debug") !== -1,
31
+ LEVEL: 0,
32
+ PREFIX: "GiphyJS",
33
+ debug: (...msg) => {
34
+ if (Logger.ENABLED && Logger.LEVEL <= 0 /* DEBUG */) {
35
+ console.debug(Logger.PREFIX, ...msg);
36
+ }
37
+ },
38
+ info: (...msg) => {
39
+ if (Logger.ENABLED && Logger.LEVEL <= 1 /* INFO */) {
40
+ console.info(Logger.PREFIX, ...msg);
41
+ }
42
+ },
43
+ warn: (...msg) => {
44
+ if (Logger.ENABLED && Logger.LEVEL <= 2 /* WARN */) {
45
+ console.warn(Logger.PREFIX, ...msg);
46
+ }
47
+ },
48
+ error: (...msg) => {
49
+ if (Logger.ENABLED && Logger.LEVEL <= 3 /* ERROR */) {
50
+ console.error(Logger.PREFIX, ...msg);
51
+ }
52
+ }
53
+ };
54
+
55
+ // src/bestfit.ts
56
+ var closestArea = (width, height, renditions) => {
57
+ let currentBest = Infinity;
58
+ let result;
59
+ renditions.forEach((rendition) => {
60
+ const widthPercentage = rendition.width / width;
61
+ const heightPercentage = rendition.height / height;
62
+ const areaPercentage = widthPercentage * heightPercentage;
63
+ const testBest = Math.abs(1 - areaPercentage);
64
+ if (testBest < currentBest) {
65
+ currentBest = testBest;
66
+ result = rendition;
67
+ }
68
+ });
69
+ return result;
70
+ };
71
+ var SCALE_UP_MAX_PIXELS = 50;
72
+ var setRenditionScaleUpMaxPixels = (pixels) => {
73
+ Logger.debug(`@giphy/js-util set rendition selection scale up max pixels to ${pixels}`);
74
+ SCALE_UP_MAX_PIXELS = pixels;
75
+ };
76
+ function bestfit(renditions, width, height, scaleUpMaxPixels = SCALE_UP_MAX_PIXELS) {
77
+ let [largestRendition] = renditions;
78
+ const testRenditions = renditions.filter((rendition) => {
79
+ if (rendition.width * rendition.height > largestRendition.width * largestRendition.height) {
80
+ largestRendition = rendition;
81
+ }
82
+ return width - rendition.width <= scaleUpMaxPixels && height - rendition.height <= scaleUpMaxPixels;
83
+ });
84
+ if (testRenditions.length === 0) {
85
+ return largestRendition;
86
+ }
87
+ return closestArea(width, height, testRenditions);
88
+ }
89
+ var bestfit_default = bestfit;
90
+
91
+ // src/collections.ts
92
+ function mapValues(object, mapFn) {
93
+ if (Array.isArray(object)) {
94
+ throw `This map is just for objects, just use array.map for arrays`;
95
+ }
96
+ return Object.keys(object).reduce((result, key) => {
97
+ result[key] = mapFn(object[key], key);
98
+ return result;
99
+ }, {});
100
+ }
101
+ function forEach(object, mapFn) {
102
+ if (Array.isArray(object)) {
103
+ throw `This map is just for objects, just use array.forEach for arrays`;
104
+ }
105
+ return Object.keys(object).forEach((key) => {
106
+ mapFn(object[key], key);
107
+ });
108
+ }
109
+ function take(arr, count = 0) {
110
+ return arr.slice(0, count);
111
+ }
112
+ function without(arr, values) {
113
+ return arr.filter((val) => values.indexOf(val) === -1);
114
+ }
115
+ function pick(object, pick2) {
116
+ const res = {};
117
+ pick2.forEach((key) => {
118
+ if (object[key] !== void 0) {
119
+ res[key] = object[key];
120
+ }
121
+ });
122
+ return res;
123
+ }
124
+
125
+ // src/get-client-rect-from-el.ts
126
+ var getClientRect = (el) => {
127
+ let left = 0;
128
+ let top = 0;
129
+ const width = el.offsetWidth;
130
+ const height = el.offsetHeight;
131
+ do {
132
+ left += el.offsetLeft;
133
+ top += el.offsetTop;
134
+ el = el.offsetParent;
135
+ } while (el);
136
+ const result = {
137
+ left,
138
+ top,
139
+ width,
140
+ height,
141
+ right: left + width,
142
+ bottom: top + height,
143
+ x: left,
144
+ y: top
145
+ };
146
+ return __spreadProps(__spreadValues({}, result), { toJSON: () => JSON.stringify(result) });
147
+ };
148
+ var get_client_rect_from_el_default = getClientRect;
149
+
150
+ // src/get-pingback-id.ts
151
+ import { v4 as uuid } from "uuid";
152
+ var pingbackId = "";
153
+ var idLength = 16;
154
+ var noUUIDRandom = () => {
155
+ let result = "";
156
+ const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
157
+ const charactersLength = characters.length;
158
+ for (let i = 0; i < idLength; i++) {
159
+ result += characters.charAt(Math.floor(Math.random() * charactersLength));
160
+ }
161
+ return result;
162
+ };
163
+ var getPingbackId = () => {
164
+ if (!pingbackId) {
165
+ try {
166
+ pingbackId = sessionStorage.getItem("giphyPingbackId");
167
+ } catch (_) {
168
+ }
169
+ if (!pingbackId) {
170
+ const hexTime = (/* @__PURE__ */ new Date()).getTime().toString(16);
171
+ try {
172
+ pingbackId = `${hexTime}${uuid().replace(/-/g, "")}`.substring(0, idLength);
173
+ } catch (error) {
174
+ pingbackId = noUUIDRandom();
175
+ }
176
+ try {
177
+ sessionStorage.setItem("giphyPingbackId", pingbackId);
178
+ } catch (_) {
179
+ }
180
+ }
181
+ }
182
+ return pingbackId;
183
+ };
184
+ var get_pingback_id_default = getPingbackId;
185
+
186
+ // src/webp-check.ts
187
+ var SUPPORTS_WEBP = null;
188
+ var checkIfWebP = new Promise((resolve) => {
189
+ if (typeof Image === "undefined") {
190
+ resolve(false);
191
+ }
192
+ const webp = new Image();
193
+ webp.onload = () => {
194
+ SUPPORTS_WEBP = true;
195
+ resolve(SUPPORTS_WEBP);
196
+ };
197
+ webp.onerror = () => {
198
+ SUPPORTS_WEBP = false;
199
+ resolve(SUPPORTS_WEBP);
200
+ };
201
+ webp.src = "data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA";
202
+ });
203
+
204
+ // src/gif-utils.ts
205
+ var getSpecificRendition = ({ images, is_sticker: isSticker }, renditionLabel, isStill = false, useVideo = false) => {
206
+ if (!images || !renditionLabel)
207
+ return "";
208
+ isStill = isStill && !useVideo;
209
+ const rendition = images[`${renditionLabel}${isStill ? "_still" : ""}`];
210
+ if (rendition) {
211
+ if (isSticker || isStill) {
212
+ return rendition.url;
213
+ }
214
+ const webP = SUPPORTS_WEBP && rendition.webp;
215
+ return useVideo ? rendition.mp4 : webP || rendition.url;
216
+ }
217
+ return "";
218
+ };
219
+ var getBestVideo = (video, width, height) => {
220
+ let assets = video == null ? void 0 : video.assets;
221
+ if (assets) {
222
+ assets = __spreadValues({}, assets);
223
+ delete assets.source;
224
+ const filteredAssets = Object.values(assets).sort((a, b) => a.width - b.width);
225
+ return bestfit_default(filteredAssets, width, height);
226
+ }
227
+ };
228
+ var getRenditions = (type, images, video) => type === "video" && video && video.previews && !Object.keys(images).length ? video.previews : images;
229
+ var getBestRendition = (images, gifWidth, gifHeight, scaleUpMaxPixels) => {
230
+ const checkRenditions = pick(images, [
231
+ "original",
232
+ "fixed_width",
233
+ "fixed_height",
234
+ "fixed_width_small",
235
+ "fixed_height_small"
236
+ ]);
237
+ const testImages = Object.entries(checkRenditions).map(([renditionName, val]) => __spreadValues({
238
+ renditionName
239
+ }, val));
240
+ return bestfit_default(testImages, gifWidth, gifHeight, scaleUpMaxPixels);
241
+ };
242
+ var getBestRenditionUrl = ({ images, video, type }, gifWidth, gifHeight, options = { isStill: false, useVideo: false }) => {
243
+ if (!gifWidth || !gifHeight || !images)
244
+ return "";
245
+ const { useVideo, isStill, scaleUpMaxPixels } = options;
246
+ const renditions = getRenditions(type, images, video);
247
+ const { renditionName } = getBestRendition(renditions, gifWidth, gifHeight, scaleUpMaxPixels);
248
+ const key = `${renditionName}${isStill && !useVideo ? "_still" : ""}`;
249
+ const rendition = renditions[key];
250
+ const match = useVideo ? rendition.mp4 : SUPPORTS_WEBP && rendition.webp ? rendition.webp : rendition.url;
251
+ return match || "";
252
+ };
253
+ var getGifHeight = ({ images }, gifWidth) => {
254
+ const { fixed_width } = images;
255
+ if (fixed_width) {
256
+ const { width, height } = fixed_width;
257
+ const aspectRatio = width / height;
258
+ return Math.round(gifWidth / aspectRatio);
259
+ }
260
+ return 0;
261
+ };
262
+ var getGifWidth = ({ images }, gifHeight) => {
263
+ const { fixed_width } = images;
264
+ if (fixed_width) {
265
+ const { width, height } = fixed_width;
266
+ const aspectRatio = width / height;
267
+ return Math.round(gifHeight * aspectRatio);
268
+ }
269
+ return 0;
270
+ };
271
+ var getAltText = ({ alt_text, user, tags = [], is_sticker = false, title = "" }) => {
272
+ if (alt_text) {
273
+ return alt_text;
274
+ }
275
+ if (title) {
276
+ return title;
277
+ }
278
+ const username = user && user.username || "";
279
+ const filteredTags = take(without(tags, ["transparent"]), username ? 4 : 5);
280
+ return `${username ? `${username} ` : ``}${filteredTags.join(" ")} ${is_sticker ? "Sticker" : "GIF"}`;
281
+ };
282
+
283
+ // src/sdk-headers.ts
284
+ var gl = (typeof window !== "undefined" ? window : global) || {};
285
+ gl._GIPHY_SDK_HEADERS_ = gl._GIPHY_SDK_HEADERS_ || (gl.Headers ? new gl.Headers({
286
+ "X-GIPHY-SDK-PLATFORM": "web"
287
+ }) : void 0);
288
+ var getGiphySDKRequestHeaders = () => gl._GIPHY_SDK_HEADERS_;
289
+ var appendGiphySDKRequestHeader = (key, value) => {
290
+ var _a;
291
+ return (_a = getGiphySDKRequestHeaders()) == null ? void 0 : _a.set(key, value);
292
+ };
293
+ var appendGiphySDKRequestParam = (key, value) => {
294
+ var _a;
295
+ return (_a = getGiphySDKRequestHeaders()) == null ? void 0 : _a.set(key, value);
296
+ };
297
+ export {
298
+ LogLevel,
299
+ Logger,
300
+ appendGiphySDKRequestHeader,
301
+ appendGiphySDKRequestParam,
302
+ bestfit_default as bestfit,
303
+ checkIfWebP,
304
+ forEach,
305
+ getAltText,
306
+ getBestRendition,
307
+ getBestRenditionUrl,
308
+ getBestVideo,
309
+ get_client_rect_from_el_default as getClientRect,
310
+ getGifHeight,
311
+ getGifWidth,
312
+ getGiphySDKRequestHeaders,
313
+ get_pingback_id_default as getPingbackId,
314
+ getSpecificRendition,
315
+ mapValues,
316
+ pick,
317
+ setRenditionScaleUpMaxPixels,
318
+ take,
319
+ without
320
+ };
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "scripts": {
3
+ "lint": "run -T eslint . --ext .ts,.tsx",
4
+ "clean": "rm -rf ./dist",
5
+ "dev": "tsc --watch",
6
+ "build": "run -T tsup src/index.ts --format cjs,esm --dts && run -T publint",
7
+ "prepublish": "npm run clean && npm run build",
8
+ "test": "run -T jest --config ./jestconfig.js",
9
+ "test:watch": "run -T jest --config ./jestconfig.js --watchAll"
10
+ },
11
+ "name": "@giphy/js-util",
12
+ "version": "0.0.0-canary-20230620165510",
13
+ "description": "Shared giphy js utils",
14
+ "homepage": "https://github.com/Giphy/giphy-js/tree/master/packages/util",
15
+ "main": "dist/index.cjs",
16
+ "types": "dist/index.d.ts",
17
+ "module": "dist/index.js",
18
+ "type": "module",
19
+ "sideEffects": false,
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js",
24
+ "require": "./dist/index.cjs"
25
+ },
26
+ "./package.json": "./package.json"
27
+ },
28
+ "files": [
29
+ "dist/",
30
+ "src/**/*"
31
+ ],
32
+ "license": "MIT",
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "dependencies": {
37
+ "@giphy/js-types": "*",
38
+ "dompurify": "^2.2.2",
39
+ "uuid": "^9.0.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/dompurify": "^2.0.4",
43
+ "@types/uuid": "^8.3.0",
44
+ "typescript": "^5.0.4"
45
+ }
46
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "env": {
3
+ "jest": true
4
+ }
5
+ }
@@ -0,0 +1,167 @@
1
+ import { IGif, IImages, ImageAllTypes, IUser } from '@giphy/js-types'
2
+ import { forEach, mapValues, pick, take, without } from '../collections'
3
+ import getPingbackId from '../get-pingback-id'
4
+ import { getAltText, getBestRenditionUrl, getGifHeight, getGifWidth, getSpecificRendition } from '../gif-utils'
5
+
6
+ describe('response parsing', () => {
7
+ test('getGifHeight getGifWidth', () => {
8
+ const gif = {
9
+ images: {
10
+ fixed_width: {
11
+ width: 10,
12
+ height: 100,
13
+ },
14
+ },
15
+ }
16
+ expect(getGifHeight(gif as IGif, 50)).toBe(500)
17
+ expect(getGifHeight({ images: {} } as IGif, 50)).toBe(0)
18
+ expect(getGifWidth(gif as IGif, 50)).toBe(5)
19
+ expect(getGifWidth({ images: {} } as IGif, 50)).toBe(0)
20
+ })
21
+
22
+ test('getAltText', () => {
23
+ expect(getAltText({ title: 'title' } as IGif)).toBe(`title`)
24
+ const user: Partial<IUser> = {
25
+ username: 'jester',
26
+ }
27
+ const dummyGif: Partial<IGif> = {
28
+ id: 12345,
29
+ user: user as IUser,
30
+ tags: ['hi', 'bye', 'transparent'],
31
+ }
32
+ expect(getAltText(dummyGif as IGif)).toBe(`${user.username} hi bye GIF`)
33
+ const dummyGifNoUser: Partial<IGif> = {
34
+ id: 12345,
35
+ tags: ['hi', 'bye', 'hola', 'adios', 'bonjour', 'au revoir', 'ciao', 'arrivederci'],
36
+ }
37
+ expect(getAltText(dummyGifNoUser as IGif)).toBe(`hi bye hola adios bonjour GIF`)
38
+ const dummySticker: Partial<IGif> = {
39
+ id: 12345,
40
+ is_sticker: true,
41
+ tags: ['hi', 'bye', 'hola', 'adios', 'bonjour', 'au revoir', 'ciao', 'arrivederci'],
42
+ }
43
+ expect(getAltText(dummySticker as IGif)).toBe(`hi bye hola adios bonjour Sticker`)
44
+ })
45
+
46
+ test('getBestRenditionUrl', () => {
47
+ const fixedWidth: Partial<ImageAllTypes> = {
48
+ width: 10,
49
+ height: 10,
50
+ url: 'fixed_width url',
51
+ webp: 'fixed_width webp',
52
+ mp4: 'fixed_width mp4',
53
+ }
54
+ const fixedWidthStill: Partial<ImageAllTypes> = {
55
+ width: 10,
56
+ height: 10,
57
+ url: 'fixed_width url still',
58
+ webp: 'fixed_width_still webp',
59
+ mp4: 'fixed_width mp4?',
60
+ }
61
+ const images: Partial<IImages> = {
62
+ fixed_width: fixedWidth as ImageAllTypes,
63
+ fixed_width_still: fixedWidthStill as ImageAllTypes,
64
+ }
65
+ const dummyGif: Partial<IGif> = {
66
+ images: images as IImages,
67
+ }
68
+ expect(getBestRenditionUrl(dummyGif as IGif, 10, 10)).toBe(fixedWidth.url)
69
+ expect(getBestRenditionUrl(dummyGif as IGif, 10, 10, { isStill: true })).toBe(fixedWidthStill.url)
70
+ expect(getBestRenditionUrl(dummyGif as IGif, 10, 10, { useVideo: true })).toBe(fixedWidth.mp4)
71
+ expect(getBestRenditionUrl(dummyGif as IGif, 10, 10)).toBe(fixedWidth.url)
72
+ expect(getBestRenditionUrl(dummyGif as IGif, 10, 10, { isStill: true })).toBe(fixedWidthStill.url)
73
+ })
74
+
75
+ test('getSpecificRendition', () => {
76
+ const fixedWidth: Partial<ImageAllTypes> = {
77
+ width: 10,
78
+ height: 10,
79
+ url: 'fixed_width url',
80
+ webp: 'fixed_width webp',
81
+ mp4: 'fixed_width mp4',
82
+ }
83
+ const fixedWidthStill: Partial<ImageAllTypes> = {
84
+ width: 10,
85
+ height: 10,
86
+ url: 'fixed_width url still',
87
+ webp: 'fixed_width_still webp',
88
+ mp4: 'fixed_width mp4?',
89
+ }
90
+ const images: Partial<IImages> = {
91
+ fixed_width: fixedWidth as ImageAllTypes,
92
+ fixed_width_still: fixedWidthStill as ImageAllTypes,
93
+ }
94
+ const dummyGif: Partial<IGif> = {
95
+ images: images as IImages,
96
+ }
97
+ expect(getSpecificRendition(dummyGif as IGif, 'fixed_width')).toBe(fixedWidth.url)
98
+ expect(getSpecificRendition(dummyGif as IGif, 'fixed_width', true)).toBe(fixedWidthStill.url)
99
+ expect(getSpecificRendition(dummyGif as IGif, 'fixed_width', true, true)).toBe(fixedWidth.mp4)
100
+ expect(getSpecificRendition(dummyGif as IGif, 'fixed_width_still', true, true)).toBe(fixedWidthStill.mp4)
101
+ expect(getSpecificRendition(dummyGif as IGif, 'fixed_width')).toBe(fixedWidth.url)
102
+ expect(getSpecificRendition(dummyGif as IGif, 'dsakfjslkj')).toBe('')
103
+ expect(getSpecificRendition({} as IGif, 'fixed_width')).toBe('')
104
+ })
105
+ })
106
+
107
+ describe('collections', () => {
108
+ test('object map', () => {
109
+ const o = Object.freeze({ one: 1, two: 2 })
110
+ expect(mapValues(o, () => 100)).toEqual({ one: 100, two: 100 })
111
+ expect(mapValues(o, (val: number) => val + 1)).toEqual({ one: 2, two: 3 })
112
+ expect(mapValues(o, (val: any, key: any) => val + key)).toEqual({ one: `1one`, two: `2two` })
113
+ try {
114
+ expect(mapValues([], (val: any, key: any) => val + key)).toEqual({ one: `1one`, two: `2two` })
115
+ } catch (error) {
116
+ expect(true).toBe(true)
117
+ }
118
+ })
119
+
120
+ test('object forEach', () => {
121
+ const o = Object.freeze({ one: 1, two: 2 })
122
+ forEach(o, (val: number, key: string) => {
123
+ switch (key) {
124
+ case 'one':
125
+ expect(val).toBe(1)
126
+ break
127
+ default:
128
+ expect(val).toBe(2)
129
+ break
130
+ }
131
+ })
132
+
133
+ try {
134
+ expect(forEach([], (val: any, key: any) => val + key)).toEqual({ one: `1one`, two: `2two` })
135
+ } catch (error) {
136
+ expect(true).toBe(true)
137
+ }
138
+ })
139
+
140
+ test('array take', () => {
141
+ const test = ['a', 'b', 'c']
142
+ expect(take(test, 1)).toEqual(['a'])
143
+ expect(take(test, 2)).toEqual(['a', 'b'])
144
+ expect(take(test, 5)).toEqual(['a', 'b', 'c'])
145
+ })
146
+
147
+ test('array without', () => {
148
+ const test = ['a', 'b', 'c']
149
+ expect(without(test, ['c', 'b'])).toEqual(['a'])
150
+ expect(without(test, ['c'])).toEqual(['a', 'b'])
151
+ expect(without(test, ['sfsdfs'])).toEqual(['a', 'b', 'c'])
152
+ })
153
+
154
+ test('object pick', () => {
155
+ const o = Object.freeze({ one: 1, two: 2 })
156
+ const res = pick(o, ['one'])
157
+ expect(res).toEqual({ one: 1 })
158
+ // @ts-ignore
159
+ const unmatchedProperty = pick({ g: 123 }, ['b'])
160
+ expect(unmatchedProperty).toEqual({})
161
+ })
162
+
163
+ test('getRandomId', () => {
164
+ const id = getPingbackId()
165
+ expect(id.length).toEqual(16)
166
+ })
167
+ })