1
+ import { UrlParser , UrlTransformer } from "../types.ts" ;
2
+ import { toUrl } from "../utils.ts" ;
3
+
4
+ export interface ImageEngineParams {
5
+ host ?: number ;
6
+ width ?: number ;
7
+ height ?: number ;
8
+ autoWidthWithFallback ?: number ;
9
+ auto_width_fallback ?: number ;
10
+ scaleToScreenWidth ?: number ;
11
+ scale_to_screen_width ?: number ;
12
+ crop ?: number ;
13
+ outputFormat ?: string ;
14
+ format ?: string ;
15
+ fitMethod ?: string ;
16
+ fit ?: string ;
17
+ compression ?: number ;
18
+ sharpness ?: number ;
19
+ rotate ?: number ;
20
+ keepMeta ?: boolean ;
21
+ keep_meta ?: boolean ;
22
+ noOptimization ?: boolean ;
23
+ no_optimization ?: boolean ;
24
+ force_download ?: boolean ;
25
+ max_device_pixel_ratio ?: number ;
26
+ maxDevicePixelRatio ?: number ;
27
+ }
28
+
29
+ export const OBJECT_TO_DIRECTIVES_MAP : { [ key : string ] : string } = {
30
+ width : "w" ,
31
+ height : "h" ,
32
+ autoWidthWithFallback : "w_auto" ,
33
+ auto_width_fallback : "w_auto" ,
34
+ scaleToScreenWidth : "pc" ,
35
+ scale_to_screen_width : "pc" ,
36
+ crop : "cr" ,
37
+ outputFormat : "f" ,
38
+ format : "f" ,
39
+ fit : "m" ,
40
+ fitMethod : "m" ,
41
+ compression : "cmpr" ,
42
+ sharpness : "s" ,
43
+ rotate : "r" ,
44
+ inline : "in" ,
45
+ keepMeta : "meta" ,
46
+ keep_meta : "meta" ,
47
+ noOptimization : "pass" ,
48
+ no_optimization : "pass" ,
49
+ force_download : "dl" ,
50
+ max_device_pixel_ratio : "maxdpr" ,
51
+ maxDevicePixelRatio : "maxdpr"
52
+ } ;
53
+
54
+ export const parse : UrlParser < ImageEngineParams > = (
55
+ imageUrl ,
56
+ ) => {
57
+ const parsedUrl = toUrl ( imageUrl ) ;
58
+ const paramArray = getParameterArray ( parsedUrl ) ;
59
+ const baseUrl = getBaseUrl ( parsedUrl ) ;
60
+ let width = undefined , height = undefined , format = undefined ;
61
+ const params : Record < string , string > = { } ;
62
+ if ( paramArray . length > 0 ) {
63
+ paramArray . forEach ( ( para :string ) => {
64
+ let key_value = para . split ( "_" )
65
+ if ( key_value . length > 1 ) {
66
+ switch ( key_value [ 0 ] ) {
67
+ case 'w' :
68
+ width = Number ( key_value [ 1 ] ) ;
69
+ break ;
70
+ case 'h' :
71
+ height = Number ( key_value [ 1 ] ) ;
72
+ break ;
73
+ case 'f' :
74
+ format = key_value [ 1 ] ;
75
+ break ;
76
+ default :
77
+ if ( Object . values ( OBJECT_TO_DIRECTIVES_MAP ) . includes ( key_value [ 0 ] ) ) {
78
+ let directive : string = getDirective ( key_value [ 0 ] )
79
+ params [ directive ] = key_value [ 1 ] ;
80
+ }
81
+ }
82
+ }
83
+ } ) ;
84
+ }
85
+ return {
86
+ base : baseUrl ,
87
+ width,
88
+ height,
89
+ format,
90
+ params,
91
+ cdn : "imageengine" ,
92
+ } ;
93
+ } ;
94
+
95
+ export function getDirective ( key : string ) :string {
96
+ let keyArray = Object . keys ( OBJECT_TO_DIRECTIVES_MAP )
97
+ let directive = keyArray . find ( k => OBJECT_TO_DIRECTIVES_MAP [ k ] === key ) || ""
98
+ return directive ;
99
+ } ;
100
+
101
+ export function getParameterArray ( url : URL ) {
102
+ let url_string = url . toString ( ) ;
103
+ let paramArray :any = [ ]
104
+ if ( url_string ) {
105
+ let splitURL : string [ ] = url_string . split ( "imgeng=" ) ;
106
+ if ( splitURL . length > 1 ) {
107
+ paramArray = splitURL [ 1 ] . split ( "/" )
108
+ }
109
+ }
110
+ return paramArray ;
111
+ } ;
112
+
113
+ export function getBaseUrl ( url : URL ) {
114
+ let url_string = url . toString ( ) ;
115
+ let baseUrl :string = ""
116
+ if ( url_string ) {
117
+ let splitURL : string [ ] = url_string . split ( "imgeng=" ) ;
118
+ if ( splitURL . length > 1 ) {
119
+ baseUrl = splitURL [ 0 ] . slice ( 0 , - 1 )
120
+ }
121
+ else
122
+ baseUrl = url_string ;
123
+ }
124
+ return baseUrl ;
125
+ } ;
126
+
127
+ export const transform : UrlTransformer = (
128
+ { url : originalUrl , width, height, format} ,
129
+ ) => {
130
+ const url = toUrl ( originalUrl ) ;
131
+ const src = getBaseUrl ( url ) ;
132
+ let directives : Record < string , any > = { } ;
133
+ const param : [ ] = url . toString ( ) === src ? [ ] : getParameterArray ( url ) ;
134
+ if ( param . length ) {
135
+ directives = getDirectives ( param )
136
+ }
137
+ if ( width )
138
+ directives [ "width" ] = width ;
139
+ if ( height )
140
+ directives [ "height" ] = height ;
141
+ if ( format )
142
+ directives [ "format" ] = format ;
143
+ if ( ! directives . hasOwnProperty ( 'fit' ) ) {
144
+ directives = { ...directives , "fit" : "cropbox" } ;
145
+ }
146
+ let directives_string = build_IE_directives ( directives ) ;
147
+ let query_string = build_IE_query_string ( directives_string ) ;
148
+ let query_prefix = query_string === "" ? "" : ( src . includes ( "?" ) ? "&" : "?" ) ;
149
+ return `${ src } ${ query_prefix } ${ query_string } ` ;
150
+ } ;
151
+
152
+ export function build_IE_directives ( directives :any ) : string {
153
+ return Object . entries ( directives ) . reduce ( ( acc , [ k , v ] ) => {
154
+ return acc + maybe_create_directive ( k , v )
155
+ } , "" ) ;
156
+ } ;
157
+
158
+ export function build_IE_query_string ( directives_string : string ) : string {
159
+ if ( directives_string && directives_string !== "" ) {
160
+ return `imgeng=${ directives_string } ` ;
161
+ }
162
+ return ""
163
+ } ;
164
+
165
+ export function maybe_create_directive ( directive : string , value : any ) : string {
166
+ let translated_directive = OBJECT_TO_DIRECTIVES_MAP [ directive ] ;
167
+
168
+ if ( translated_directive && ( value || value === 0 ) ) {
169
+ return `/${ translated_directive } _${ value } ` ;
170
+ }
171
+ return "" ;
172
+ } ;
173
+
174
+ export function getDirectives ( paramArray : [ ] ) : { } {
175
+ let directives : Record < string , any > = { } ;
176
+ paramArray . forEach ( ( para :string ) => {
177
+ let keyValue = para . split ( "_" ) ;
178
+ if ( keyValue . length > 1 ) {
179
+ let key = keyValue [ 0 ] ;
180
+ let value = keyValue [ 1 ] ;
181
+ let directiveKey = getDirective ( key ) ;
182
+ if ( directiveKey ) {
183
+ directives [ directiveKey ] = value ;
184
+ }
185
+ }
186
+ } )
187
+ return directives
188
+ }
0 commit comments