Skip to content

Commit a15bc81

Browse files
committed
fix: Resolve SDK comments
1 parent bf79dea commit a15bc81

File tree

7 files changed

+126
-115
lines changed

7 files changed

+126
-115
lines changed

LICENSE.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
1-
Copyright 2025 ImageKit Private Limited
1+
MIT License
22

3-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
3+
Copyright (c) 2025 ImageKit Private Limited
44

5-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
611

7-
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 42 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { Component, AfterViewInit, OnInit, ElementRef, Input, OnChanges } from '@angular/core';
22
import { ImagekitService } from '../imagekit-angular.service';
33
import { Dict, QueryParameters, IkImageComponentOptions } from '../utility/ik-type-def-collection';
4-
import { getInt } from '../utility/utils';
4+
import { getInt, namedNodeMapToObject, setElementAttributes } from '../utility/utils';
55
import { buildSrc, getResponsiveImageAttributes, SrcOptions } from '@imagekit/javascript';
66
import type { Transformation } from '@imagekit/javascript'
77

88
@Component({
99
selector: 'ik-image',
10-
template: `<img src='' (load)="onImageLoaded($event)">`,
10+
template: `<img src=''>`,
1111
})
1212
export class IkImageComponent implements AfterViewInit, OnInit, OnChanges {
1313
@Input('src') src: string = "";
@@ -17,44 +17,41 @@ export class IkImageComponent implements AfterViewInit, OnInit, OnChanges {
1717
@Input('queryParameters') queryParameters: QueryParameters;
1818
@Input('loading') loading: string = "lazy";
1919
@Input('width') width: number | string;
20-
@Input('height') height: string;
20+
@Input('height') height: number | string;
2121
@Input('responsive') responsive: boolean = true;
2222
@Input('deviceBreakpoints') deviceBreakpoints: number[];
2323
@Input('imageBreakpoints') imageBreakpoints: number[];
2424
@Input('sizes') sizes: string;
2525
url = '';
2626
srcset = '';
27+
selector = 'ik-image';
2728

28-
constructor(private el: ElementRef, private imagekit: ImagekitService) {
29-
}
29+
constructor(private el: ElementRef, private imagekit: ImagekitService) { }
3030

3131
ngOnInit(): void {
32-
const options: IkImageComponentOptions = {
33-
src: this.src,
34-
urlEndpoint: this.urlEndpoint ? this.urlEndpoint : this.imagekit._ikInstance.options.urlEndpoint,
35-
transformation: this.transformation,
36-
transformationPosition: this.transformationPosition,
37-
queryParameters: this.queryParameters,
38-
};
39-
this.setUrl(options);
32+
this.setSrcParams();
4033
}
4134

4235
ngOnChanges(): void {
43-
this.ngOnInit();
44-
this.ngAfterViewInit();
36+
this.setSrcParams();
37+
this.loadImage(this, this.url, this.srcset);
4538
}
4639

4740
ngAfterViewInit(): void {
48-
if (!this.url) {
49-
return;
50-
}
5141
this.loadImage(this, this.url, this.srcset);
5242
}
5343

54-
onImageLoaded = (event: { srcElement: { src: string; } | any }) => {
55-
// Image loaded
56-
};
57-
44+
setSrcParams(): void {
45+
const options: IkImageComponentOptions = {
46+
src: this.src,
47+
urlEndpoint: this.urlEndpoint ? this.urlEndpoint : this.imagekit.ikInstance.options.urlEndpoint,
48+
transformation: this.transformation,
49+
transformationPosition: this.transformationPosition,
50+
queryParameters: this.queryParameters,
51+
};
52+
this.setUrl(options);
53+
}
54+
5855
setUrl(options: IkImageComponentOptions): void {
5956
const widthInt = getInt(this.width);
6057

@@ -65,26 +62,35 @@ export class IkImageComponent implements AfterViewInit, OnInit, OnChanges {
6562

6663
const strictOptions = options as SrcOptions;
6764

68-
if (!this.responsive) {
69-
this.url = buildSrc(strictOptions);
65+
try {
66+
if (!this.responsive) {
67+
this.url = buildSrc(strictOptions);
68+
this.srcset = '';
69+
} else {
70+
const { src: newSrc, srcSet } = getResponsiveImageAttributes({
71+
...strictOptions,
72+
width: isNaN(widthInt) ? undefined : widthInt,
73+
sizes: this.sizes,
74+
deviceBreakpoints: this.deviceBreakpoints,
75+
imageBreakpoints: this.imageBreakpoints,
76+
})
77+
this.url = newSrc;
78+
this.srcset = srcSet;
79+
}
80+
} catch (error) {
81+
console.error("Error generating src params: ", error);
82+
this.url = '';
7083
this.srcset = '';
71-
} else {
72-
const { src: newSrc, srcSet } = getResponsiveImageAttributes({
73-
...strictOptions,
74-
width: isNaN(widthInt) ? undefined : widthInt,
75-
sizes: this.sizes,
76-
deviceBreakpoints: this.deviceBreakpoints,
77-
imageBreakpoints: this.imageBreakpoints,
78-
})
79-
this.url = newSrc;
80-
this.srcset = srcSet;
8184
}
8285
}
8386

8487
loadImage(context: IkImageComponent, url: string, srcset: string): void {
88+
if (!url) {
89+
return;
90+
}
8591
const nativeElement = context.el.nativeElement;
8692
const attributes = nativeElement.attributes;
87-
const attrsToSet = context.namedNodeMapToObject(attributes);
93+
const attrsToSet = namedNodeMapToObject(attributes);
8894
attrsToSet['src'] = url;
8995

9096
if (srcset) {
@@ -97,26 +103,6 @@ export class IkImageComponent implements AfterViewInit, OnInit, OnChanges {
97103
attrsToSet['loading'] = context.loading;
98104
}
99105
const image = nativeElement.children[0];
100-
context.setElementAttributes(image, attrsToSet);
101-
}
102-
103-
namedNodeMapToObject(source: NamedNodeMap): Dict {
104-
let target: Dict = {};
105-
Object.keys(source).forEach(index => {
106-
const name = source[index].name;
107-
const value = source[index].value;
108-
target[name] = value;
109-
});
110-
return target;
111-
};
112-
113-
setElementAttributes(element: any, attributesLiteral: Dict): void {
114-
Object.keys(attributesLiteral).forEach(attrName => {
115-
if (attrName.startsWith('ng-') || attrName.startsWith('_ng')) {
116-
element.removeAttribute(attrName);
117-
return;
118-
}
119-
element.setAttribute(attrName, attributesLiteral[attrName]);
120-
});
106+
setElementAttributes(image, attrsToSet, context.selector);
121107
}
122108
}
Lines changed: 35 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,75 @@
1-
import { Component, OnInit, ElementRef, Input } from '@angular/core';
1+
import { Component, OnInit, ElementRef, Input, OnChanges, AfterViewInit } from '@angular/core';
22
import { ImagekitService } from '../imagekit-angular.service';
33
import { IkVideoComponentOptions, QueryParameters, Dict } from '../utility/ik-type-def-collection';
44
import { buildSrc, SrcOptions } from '@imagekit/javascript';
55
import type { Transformation } from '@imagekit/javascript'
6+
import { namedNodeMapToObject, setElementAttributes } from '../utility/utils';
67

78

89
@Component({
910
selector: 'ik-video',
1011
template: `<video></video>`,
1112
})
1213

13-
export class IkVideoComponent implements OnInit {
14+
export class IkVideoComponent implements OnInit, OnChanges, AfterViewInit {
1415
@Input('urlEndpoint') urlEndpoint: string;
1516
@Input('src') src: string = "";
1617
@Input('transformation') transformation: Array<Transformation> = [];
1718
@Input('transformationPosition') transformationPosition: "path" | "query";
1819
@Input('queryParameters') queryParameters: QueryParameters;
1920
url = '';
21+
selector = 'ik-video';
2022

2123
constructor(private el: ElementRef, private imagekit: ImagekitService) { }
2224

2325
ngOnInit(): void {
24-
const options: IkVideoComponentOptions = {
25-
src: this.src,
26-
urlEndpoint: this.urlEndpoint ? this.urlEndpoint : this.imagekit._ikInstance.options.urlEndpoint,
27-
transformation: this.transformation,
28-
transformationPosition: this.transformationPosition,
29-
queryParameters: this.queryParameters,
30-
};
31-
this.setUrl(options);
26+
this.buildOptionsAndSetUrl();
3227
}
28+
3329
ngOnChanges(): void {
34-
this.ngOnInit();
35-
if (this.url) {
36-
this.ngAfterViewInit();
37-
}
30+
this.buildOptionsAndSetUrl();
31+
this.loadVideo(this.url);
3832
}
3933

4034
ngAfterViewInit(): void {
41-
if (!this.url) {
42-
return;
43-
}
4435
this.loadVideo(this.url);
4536
}
4637

47-
loadVideo(url:string): void {
48-
const nativeElement = this.el.nativeElement;
49-
const attributes = nativeElement.attributes;
50-
const attrsToSet = this.namedNodeMapToObject(attributes);
51-
attrsToSet['src'] = url;
52-
const video = nativeElement.children[0];
53-
this.setElementAttributes(video, attrsToSet);
54-
}
5538

56-
namedNodeMapToObject(source: NamedNodeMap): Dict {
57-
let target: Dict = {};
58-
Object.keys(source).forEach(index => {
59-
const name = source[index].name;
60-
const value = source[index].value;
61-
target[name] = value;
62-
});
63-
return target;
64-
};
39+
buildOptionsAndSetUrl(): void {
40+
const options: IkVideoComponentOptions = {
41+
src: this.src,
42+
urlEndpoint: this.urlEndpoint ? this.urlEndpoint : this.imagekit.ikInstance.options.urlEndpoint,
43+
transformation: this.transformation,
44+
transformationPosition: this.transformationPosition,
45+
queryParameters: this.queryParameters,
46+
};
47+
this.setUrl(options);
48+
}
6549

6650
setUrl(options: IkVideoComponentOptions): void {
6751
if (!options.urlEndpoint || options.urlEndpoint.trim() === "") {
6852
console.warn("urlEndpoint is neither provided in this component nor in any parent ImagekitService.");
6953
return null;
7054
}
7155
const strictOptions = options as SrcOptions
72-
this.url = buildSrc(strictOptions);
56+
try {
57+
this.url = buildSrc(strictOptions);
58+
} catch (error) {
59+
console.error("Error generating src: ", error);
60+
this.url = '';
61+
}
7362
}
74-
75-
setElementAttributes(element: any, attributesLiteral: Dict): void {
76-
Object.keys(attributesLiteral).forEach(attrName => {
77-
if (attrName.startsWith('ng-') || attrName.startsWith('_ng')) {
78-
element.removeAttribute(attrName);
79-
return;
80-
}
81-
// This is required otherwise video attributes like muted, controls, autoplay do not work as expected.
82-
const videoPlaybackAttributes = ['autoplay', 'muted', 'controls', 'loop'];
83-
if (videoPlaybackAttributes.includes(attrName)) {
84-
element[attrName] = true;
85-
}
86-
element.setAttribute(attrName, attributesLiteral[attrName]);
87-
});
63+
64+
loadVideo(url:string): void {
65+
if (!url) {
66+
return;
67+
}
68+
const nativeElement = this.el.nativeElement;
69+
const attributes = nativeElement.attributes;
70+
const attrsToSet = namedNodeMapToObject(attributes);
71+
attrsToSet['src'] = url;
72+
const video = nativeElement.children[0];
73+
setElementAttributes(video, attrsToSet, this.selector);
8874
}
8975
}

sdk/src/lib/imagekit-angular.service.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ export class ImagekitService {
2424
};
2525
}
2626

27-
get _ikInstance(): { options: ImageKitConfiguration } {
28-
return this.ikInstance;
29-
}
30-
3127
getUrlEndpoint(passedUrlEndpoint?: string | null): string {
3228
return passedUrlEndpoint ?? this.configuration.urlEndpoint;
3329
}

sdk/src/lib/utility/ik-type-def-collection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export interface AuthResponse {
8484
token: string;
8585
}
8686

87-
export class ImageKitConfiguration {
87+
export interface ImageKitConfiguration {
8888
urlEndpoint: SrcOptions['urlEndpoint'];
8989
transformationPosition?: SrcOptions['transformationPosition'];
9090
sdkVersion?: string;

sdk/src/lib/utility/utils.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { Dict } from "./ik-type-def-collection";
2+
13
export function getInt(x: unknown): number {
24
if (typeof x === 'undefined') {
35
return NaN
@@ -9,4 +11,31 @@ export function getInt(x: unknown): number {
911
return parseInt(x, 10)
1012
}
1113
return NaN
14+
}
15+
16+
export function namedNodeMapToObject(source: NamedNodeMap): Dict {
17+
let target: Dict = {};
18+
Object.keys(source).forEach(index => {
19+
const name = source[index].name;
20+
const value = source[index].value;
21+
target[name] = value;
22+
});
23+
return target;
24+
};
25+
26+
export function setElementAttributes(element: any, attributesLiteral: Dict, selector: string): void {
27+
Object.keys(attributesLiteral).forEach(attrName => {
28+
if (attrName.startsWith('ng-') || attrName.startsWith('_ng')) {
29+
element.removeAttribute(attrName);
30+
return;
31+
}
32+
element.setAttribute(attrName, attributesLiteral[attrName]);
33+
// This is required otherwise video attributes like muted, controls, autoplay do not work as expected.
34+
if (selector === 'ik-video') {
35+
const videoPlaybackAttributes = ['autoplay', 'muted', 'controls', 'loop'];
36+
if (videoPlaybackAttributes.includes(attrName)) {
37+
element[attrName] = true;
38+
}
39+
}
40+
});
1241
}

sdk/tests/sdk-tests/imagekit.service.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ describe("ImagekitService", () => {
99
})
1010

1111
it("should set urlEndpoint correctly", () => {
12-
expect(imagekitService._ikInstance.options.urlEndpoint).toContain(`url`)
12+
expect(imagekitService.ikInstance.options.urlEndpoint).toContain(`url`)
1313
});
1414

1515
it("getUrlEndpoint should return passed urlEndpoint when provided", () => {

0 commit comments

Comments
 (0)