Page Menu
Home
Sealhub
Search
Configure Global Search
Log In
Files
F21589039
guessResolutions.ts
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
8 KB
Referenced Files
None
Subscribers
None
guessResolutions.ts
View Options
import
{
fit
}
from
"object-fit-math"
;
import
{
Condition
,
Ranges
,
Unit
,
resolutionGuessOptions
,
}
from
"../types/guessResolutions"
;
import
{
Container
}
from
"../types/imageRouter"
;
const
sortAscFn
=
(
a
:
number
,
b
:
number
)
=>
a
-
b
;
const
fillGaps
=
(
resolutions
:
number
[])
=>
{
const
sorted_resolutions
=
resolutions
.
sort
(
sortAscFn
);
const
gap_fills
:
number
[]
=
[];
const
smallest_res
=
sorted_resolutions
[
0
],
largest_res
=
sorted_resolutions
[
sorted_resolutions
.
length
-
1
];
if
(
largest_res
)
{
let
cur_res
=
smallest_res
*
4
;
while
(
cur_res
<
largest_res
)
{
gap_fills
.
push
(
cur_res
);
cur_res
*=
2
;
}
return
gap_fills
;
}
else
return
[];
};
const
getResFromVw
=
(
vw
:
number
,
max_res
:
number
)
=>
(
vw
/
100
)
*
max_res
;
const
createRange
=
(
val1
:
number
,
val2
:
number
,
{
subtract
=
1
}
:
{
subtract
?:
number
}
=
{}
)
=>
{
if
(
val1
>
val2
)
return
[
val2
,
val1
-
subtract
];
else
return
[
val1
,
val2
-
subtract
];
};
const
rangesSortFn
=
(
a
:
number
[],
b
:
number
[])
=>
a
[
0
]
-
b
[
0
];
const
sortRanges
=
(
initialRanges
:
Ranges
,
constant_resolutions
:
number
[])
=>
{
const
screen
=
initialRanges
.
screen
.
sort
(
rangesSortFn
);
const
calculated
=
initialRanges
.
calculated
.
sort
(
rangesSortFn
);
const
ranges
=
{
screen
,
calculated
};
return
{
ranges
,
constant_resolutions
:
constant_resolutions
.
sort
(
sortAscFn
),
};
};
const
getRanges
=
({
conditions
,
min_viewport_size
,
max_viewport_size
,
}
:
{
conditions
:
Condition
[];
max_viewport_size
:
number
;
min_viewport_size
:
number
;
})
=>
{
const
constant_resolutions
:
number
[]
=
[];
let
min_conditions_count
=
0
,
max_conditions_count
=
0
;
const
ranges
:
Ranges
=
{
calculated
:
[],
screen
:
[],
};
const
conditions_len
=
conditions
.
length
;
for
(
let
i
=
0
;
i
<
conditions_len
;
i
++
)
{
const
condit
=
conditions
[
i
];
const
prev_condit
=
conditions
[
i
-
1
];
if
(
condit
.
then_unit
===
"px"
)
{
constant_resolutions
.
push
(
condit
.
then_res
);
if
(
conditions_len
===
1
)
return
sortRanges
(
ranges
,
constant_resolutions
);
continue
;
}
const
calculated_res
=
getResFromVw
(
condit
.
then_res
,
condit
.
width_condition
);
if
(
condit
.
condition_type
===
"max"
)
{
max_conditions_count
++
;
if
(
prev_condit
&&
prev_condit
.
condition_type
!==
"default"
)
{
const
end_of_range_res
=
getResFromVw
(
condit
.
then_res
,
prev_condit
.
width_condition
);
ranges
.
screen
.
push
(
createRange
(
prev_condit
.
width_condition
,
condit
.
width_condition
)
);
ranges
.
calculated
.
push
(
createRange
(
end_of_range_res
,
calculated_res
)
);
}
if
(
i
===
0
)
{
ranges
.
screen
.
push
(
createRange
(
min_viewport_size
,
condit
.
width_condition
)
);
ranges
.
calculated
.
push
(
createRange
(
min_viewport_size
,
calculated_res
)
);
}
}
else
if
(
condit
.
condition_type
===
"min"
)
{
min_conditions_count
++
;
if
(
prev_condit
&&
prev_condit
.
condition_type
!==
"default"
)
{
const
end_of_range_res
=
getResFromVw
(
condit
.
then_res
,
prev_condit
.
width_condition
);
ranges
.
calculated
.
push
(
createRange
(
calculated_res
,
end_of_range_res
)
);
ranges
.
screen
.
push
(
createRange
(
condit
.
width_condition
,
prev_condit
.
width_condition
)
);
}
if
(
i
===
0
)
{
ranges
.
calculated
.
push
(
createRange
(
calculated_res
,
getResFromVw
(
condit
.
then_res
,
max_viewport_size
),
{
subtract
:
0
}
)
);
ranges
.
screen
.
push
(
createRange
(
condit
.
width_condition
,
max_viewport_size
,
{
subtract
:
0
,
})
);
}
}
else
if
(
condit
.
condition_type
===
"default"
)
{
if
(
!
min_conditions_count
&&
!
max_conditions_count
)
{
ranges
.
screen
.
push
(
createRange
(
min_viewport_size
,
max_viewport_size
,
{
subtract
:
0
,
})
);
ranges
.
calculated
.
unshift
(
createRange
(
min_viewport_size
,
getResFromVw
(
condit
.
then_res
,
max_viewport_size
),
{
subtract
:
0
}
)
);
return
sortRanges
(
ranges
,
constant_resolutions
);
}
const
sorted_screen_ranges
=
ranges
.
screen
.
sort
(
rangesSortFn
);
const
start_range
=
sorted_screen_ranges
[
0
][
0
];
const
end_range
=
sorted_screen_ranges
[
sorted_screen_ranges
.
length
-
1
][
1
]
+
1
;
if
(
min_conditions_count
)
{
ranges
.
screen
.
push
(
createRange
(
min_viewport_size
,
start_range
));
ranges
.
calculated
.
unshift
(
createRange
(
min_viewport_size
,
getResFromVw
(
condit
.
then_res
,
start_range
)
)
);
}
else
if
(
max_conditions_count
)
{
ranges
.
screen
.
push
(
createRange
(
end_range
,
max_viewport_size
,
{
subtract
:
0
})
);
ranges
.
calculated
.
push
(
createRange
(
getResFromVw
(
condit
.
then_res
,
end_range
),
getResFromVw
(
condit
.
then_res
,
max_viewport_size
),
{
subtract
:
0
}
)
);
}
}
}
return
sortRanges
(
ranges
,
constant_resolutions
);
};
export
function
guessResolutions
(
sizes_attr
:
string
,
{
min_viewport_size
=
320
,
max_viewport_size
=
1920
,
}
:
resolutionGuessOptions
=
{},
container
?:
Container
,
image_size
?:
{
width
:
number
;
height
:
number
}
)
:
number
[]
{
const
gap_fills
:
number
[]
=
[],
resolutions
:
number
[]
=
[],
constant_resolutions
:
number
[]
=
[];
const
regex
=
/\((max|min)-width\s*:\s*(\d+)px\s*\)\s*(\d+)(vw|px)/gi
;
let
match
=
regex
.
exec
(
sizes_attr
);
const
condition_matches
=
[];
while
(
match
!==
null
)
{
condition_matches
.
push
(
match
);
match
=
regex
.
exec
(
sizes_attr
);
}
const
default_size_match
=
/(,?)\s*(\d+)(px|vw)\s*$/i
.
exec
(
sizes_attr
);
const
conditions
:
Condition
[]
=
[];
for
(
const
match
of
condition_matches
)
{
const
condition_type
=
match
[
1
]
as
"max"
|
"min"
,
width_condition
=
parseInt
(
match
[
2
]),
then_res
=
parseInt
(
match
[
3
]),
then_unit
=
match
[
4
]
as
Unit
;
conditions
.
push
({
condition_type
,
width_condition
,
then_res
,
then_unit
,
});
}
if
(
default_size_match
)
{
const
res
=
parseInt
(
default_size_match
[
2
]),
unit
=
default_size_match
[
3
]
as
Unit
;
conditions
.
push
({
condition_type
:
"default"
,
width_condition
:
0
,
then_res
:
res
,
then_unit
:
unit
,
});
}
const
{
ranges
,
constant_resolutions
:
constant_resolutions_unsorted
}
=
getRanges
({
conditions
,
min_viewport_size
,
max_viewport_size
,
});
for
(
const
range
of
ranges
.
calculated
)
{
resolutions
.
push
(...
range
,
range
[
0
]
*
2
,
range
[
1
]
*
2
);
}
for
(
const
res
of
constant_resolutions_unsorted
)
{
constant_resolutions
.
push
(
res
,
res
*
2
);
}
if
(
container
&&
image_size
)
{
const
fitted_image_size
=
fit
(
container
,
image_size
,
container
.
objectFit
||
"contain"
);
constant_resolutions
.
push
(
Math
.
min
(
image_size
.
width
,
fitted_image_size
.
width
),
Math
.
min
(
image_size
.
width
,
fitted_image_size
.
width
)
*
2
);
}
const
filtered_resolutions
=
resolutions
.
map
((
res
)
=>
{
if
(
res
<
min_viewport_size
)
{
return
min_viewport_size
;
}
else
return
Math
.
round
(
res
);
});
gap_fills
.
push
(...
fillGaps
(
filtered_resolutions
));
let
final_resolutions
=
[
...
new
Set
(
filtered_resolutions
.
concat
(...
gap_fills
,
...
constant_resolutions
)
),
].
sort
(
sortAscFn
);
if
(
image_size
)
{
const
resolutions_without_upscaling
=
final_resolutions
.
filter
(
(
r
)
=>
r
<=
image_size
.
width
);
if
(
resolutions_without_upscaling
.
length
<
final_resolutions
.
length
)
{
resolutions_without_upscaling
.
push
(
image_size
.
width
);
}
final_resolutions
=
resolutions_without_upscaling
;
}
const
result
=
Array
.
from
(
new
Set
(
final_resolutions
));
return
result
;
}
export
function
prepareResolutions
({
sizesAttr
,
resolutions
,
container
,
original_image_size
,
thumbnailSize
,
}
:
{
sizesAttr
?:
string
;
resolutions
?:
number
[];
container
?:
Container
;
original_image_size
:
{
width
:
number
;
height
:
number
};
thumbnailSize
:
number
;
})
{
if
(
!
resolutions
)
{
if
(
sizesAttr
)
{
resolutions
=
guessResolutions
(
sizesAttr
,
{},
container
,
original_image_size
);
}
else
if
(
container
)
{
resolutions
=
guessResolutions
(
`
${
container
.
width
}
px`
,
{},
container
,
original_image_size
);
}
else
{
throw
new
Error
(
"Invalid parameters. You must provide at least either: (resolutions) or (sizesAttr) or (container)"
);
}
}
resolutions
.
push
(
thumbnailSize
);
resolutions
=
Array
.
from
(
new
Set
(
resolutions
.
filter
((
width
)
=>
width
<=
original_image_size
.
width
)
)
);
if
(
resolutions
.
filter
((
l
)
=>
l
!=
thumbnailSize
).
length
==
0
)
{
// no resolutions other than the thumbnail, let's add at least one
resolutions
=
[
original_image_size
.
width
];
}
resolutions
=
resolutions
.
map
((
l
)
=>
Math
.
round
(
l
));
return
resolutions
;
}
File Metadata
Details
Attached
Mime Type
application/javascript
Expires
Sat, Nov 7, 16:21 (15 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1181916
Default Alt Text
guessResolutions.ts (8 KB)
Attached To
Mode
rRIMAGEROUTER koa-responsive-image-router
Attached
Detach File
Event Timeline