Skip to content

Commit bd14371

Browse files
authored
Merge pull request #101 from CSSSR/COM-2479
COM-2479: Добавил возможность использовать csssr.images без изменения размера изображений
2 parents 509d0b5 + 4760f22 commit bd14371

17 files changed

Lines changed: 261 additions & 78 deletions

example/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
Чтобы запустить этот пример,
44
нужно предварительно запустить imgproxy локально на 8080 порту командой
55
`docker run -e IMGPROXY_MAX_SRC_RESOLUTION=40 -p 8080:8080 -it darthsim/imgproxy`,
6-
затем выполнить `npm run run-example` из корня проекта
6+
затем выполнить `npm run dev` из корня проекта
77
и открыть в браузере http://localhost:8081/.

example/react-entry.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,58 @@ import React from 'react';
22
import ReactDOM from 'react-dom';
33
import { PictureSmart } from '../src/react';
44
import { backgroundCssSmart } from '../src/utils/backgroundCss';
5+
import { getOriginal } from '../src/utils';
56

67
// Adds 'webp' class to html element if the browser supports webp.
7-
import '../src/utils/webpDetector'
8+
import '../src/utils/webpDetector';
89

910
const oneImageForAllBreakpoints = require.context('./images/oneImageForAllBreakpoints');
1011
const differentBreakpoints = require.context('./images/differentBreakpoints');
1112

13+
const imageWithoutResize = require.context('./images/oneImageForAllBreakpoints?dontresize');
14+
15+
const myImageData = require('./images/oneImageForAllBreakpoints/all.png');
16+
const myImageWithoutResizeData = require('./images/oneImageForAllBreakpoints/all.png?dontresize');
17+
18+
// Usage example getOriginal ()
19+
console.log(getOriginal(myImageData));
20+
console.log(getOriginal(myImageWithoutResizeData));
21+
1222
ReactDOM.render(
1323
<div>
1424
<h1>Example usage of csssr.images</h1>
1525

1626
<h2>As picture tag</h2>
27+
1728
<h3>One image for all resolutions</h3>
1829
<PictureSmart requireImages={oneImageForAllBreakpoints} alt="One image for all resolutions" />
30+
1931
<h3>Image with different breakpoints</h3>
2032
<PictureSmart requireImages={differentBreakpoints} alt="Image with different breakpoints" />
2133

34+
<h3>Image without resize</h3>
35+
<PictureSmart requireImages={imageWithoutResize} alt="Image without resize" />
2236

2337
<h2>As background css</h2>
38+
2439
<h3>One image for all resolutions</h3>
2540
<div className="one-image-for-all-resolutions" style={{ width: '100%', height: '100%' }}>
2641
One image for all resolutions on background
2742
</div>
2843
<style>{backgroundCssSmart('.one-image-for-all-resolutions', oneImageForAllBreakpoints)}</style>
44+
2945
<h3>Different breakpoints</h3>
3046
<div className="different-breakpoints" style={{ width: '100%', height: '100%' }}>
3147
Image with different breakpoints on background
3248
</div>
3349
<style>{backgroundCssSmart('.different-breakpoints', differentBreakpoints)}</style>
50+
51+
<h3>Image without resize</h3>
52+
53+
<div className="image-without-resize" style={{ width: '100%', height: '100%' }}>
54+
Image without resize on background
55+
</div>
56+
<style>{backgroundCssSmart('.image-without-resize', imageWithoutResize)}</style>
3457
</div>,
3558
document.getElementById('app'),
3659
);

example/webpack.config.ts

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,52 @@
11
import path from 'path';
22
import webpack from 'webpack';
3+
import ip from 'ip';
34
import { Plugin } from '../src/webpack';
5+
import { Dpr } from '../src/types';
6+
7+
const handleImagesForOriginalPixelRatio = (originalPixelRatio: Dpr) => {
8+
return {
9+
use: [
10+
{
11+
loader: path.resolve(__dirname, '../src/index.ts'),
12+
options: {
13+
breakpoints: [
14+
{
15+
name: 'mobile',
16+
maxWidth: 767,
17+
},
18+
{
19+
name: 'tablet',
20+
minWidth: 768,
21+
maxWidth: 1279,
22+
},
23+
{
24+
name: 'desktop',
25+
minWidth: 1280,
26+
},
27+
],
28+
imgproxy: {
29+
disable: false,
30+
imagesHost: process.env.HOST || `http://${ip.address()}:8081`,
31+
host: process.env.IMGPROXY_HOST || 'http://localhost:8080',
32+
},
33+
originalPixelRatio,
34+
},
35+
},
36+
{
37+
loader: 'file-loader',
38+
options: {
39+
publicPath: '/build',
40+
name:
41+
process.env.NODE_ENV === 'development'
42+
? '[path][name].[ext]'
43+
: '[path][name]-[hash:8].[ext]',
44+
esModule: false,
45+
},
46+
},
47+
],
48+
};
49+
};
450

551
const config: webpack.Configuration = {
652
mode: 'production',
@@ -23,42 +69,13 @@ const config: webpack.Configuration = {
2369
},
2470
{
2571
test: /\.(jpe?g|png|gif)$/,
26-
use: [
72+
oneOf: [
2773
{
28-
loader: path.resolve(__dirname, '../src/index.ts'),
29-
options: {
30-
breakpoints: [
31-
{
32-
name: 'mobile',
33-
maxWidth: 767,
34-
},
35-
{
36-
name: 'tablet',
37-
minWidth: 768,
38-
maxWidth: 1279,
39-
},
40-
{
41-
name: 'desktop',
42-
minWidth: 1280,
43-
},
44-
],
45-
imgproxy: {
46-
disable: false,
47-
imagesHost: process.env.HOST || 'http://192.168.1.134:8081',
48-
host: process.env.IMGPROXY_HOST || 'http://localhost:8080',
49-
},
50-
},
74+
resourceQuery: /dontresize/,
75+
...handleImagesForOriginalPixelRatio('1x'),
5176
},
5277
{
53-
loader: 'file-loader',
54-
options: {
55-
publicPath: '/build',
56-
name:
57-
process.env.NODE_ENV === 'development'
58-
? '[path][name].[ext]'
59-
: '[path][name]-[hash:8].[ext]',
60-
esModule: false,
61-
},
78+
...handleImagesForOriginalPixelRatio('3x'),
6279
},
6380
],
6481
},

package-lock.json

Lines changed: 15 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
"eslint-plugin-react": "^7.20.3",
3939
"file-loader": "^6.0.0",
4040
"http-server": "^0.12.3",
41-
"jest": "^26.1.0",
41+
"ip": "^1.1.5",
42+
"jest": "^26.0.1",
4243
"loader-utils": "^2.0.0",
4344
"prettier": "^2.0.5",
4445
"ts-jest": "^26.1.3",
@@ -49,6 +50,7 @@
4950
"webpack-cli": "^3.3.12"
5051
},
5152
"dependencies": {
53+
"@types/ip": "^1.1.0",
5254
"imgproxy": "^0.1.2",
5355
"react": "^16.13.1",
5456
"react-dom": "^16.13.1"

src/types.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
export type Dpr = '1x' | '2x' | '3x';
22

3+
export type CompressionRatio = {
4+
'1x': number;
5+
'2x'?: number;
6+
'3x'?: number;
7+
};
8+
39
export type SrcSet = {
4-
[dpr in Dpr]: string;
10+
'1x': string;
11+
'2x'?: string;
12+
'3x'?: string;
513
};
614

715
export type ExtensionSrcSet = {

src/utils/__tests__/backgroundCss.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,3 +397,34 @@ test('backgroundCss multiple breakpoints, png and webp', () => {
397397
}
398398
}`);
399399
});
400+
401+
test('backgroundCss all breakpoints, png and webp, one pixel ratio', () => {
402+
expect(
403+
backgroundCss('.my-selector', [
404+
{
405+
breakpointMedia: null,
406+
srcSets: [
407+
{
408+
extension: 'png',
409+
srcSet: {
410+
'1x': '/mobile.all.1x.png',
411+
},
412+
},
413+
{
414+
extension: 'webp',
415+
srcSet: {
416+
'1x': '/mobile.all.1x.webp',
417+
},
418+
},
419+
],
420+
},
421+
]),
422+
).toBeSameCss(`
423+
.my-selector {
424+
background-image: url(/mobile.all.1x.png);
425+
}
426+
html.webp .my-selector {
427+
background-image: url(/mobile.all.1x.webp);
428+
}
429+
`);
430+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { getCompressionRatio } from '../index';
2+
3+
test('Pixel ratios 1x', () => {
4+
expect(getCompressionRatio(['1x'])).toStrictEqual({ '1x': 0 });
5+
});
6+
7+
test('Pixel ratios 1x, 2x', () => {
8+
expect(getCompressionRatio(['1x', '2x'])).toStrictEqual({ '1x': 0.5, '2x': 0 });
9+
});
10+
11+
test('Pixel ratios 1x, 2x, 3x', () => {
12+
expect(getCompressionRatio(['1x', '2x', '3x'])).toStrictEqual({
13+
'1x': 0.33333,
14+
'2x': 0.66667,
15+
'3x': 0,
16+
});
17+
});

src/utils/backgroundCss.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,31 @@ const srcSetCss = (selector: string, sources: ExtensionSrcSet[]): string => {
1717
(acc, source) => {
1818
const finalSelector = getSelector(selector, source.extension);
1919
acc['1x'].push(`${finalSelector} { background-image: url(${source.srcSet['1x']}); }`);
20-
acc['2x'].push(`${finalSelector} { background-image: url(${source.srcSet['2x']}); }`);
21-
acc['3x'].push(`${finalSelector} { background-image: url(${source.srcSet['3x']}); }`);
20+
source.srcSet['2x'] &&
21+
acc['2x'].push(`${finalSelector} { background-image: url(${source.srcSet['2x']}); }`);
22+
source.srcSet['3x'] &&
23+
acc['3x'].push(`${finalSelector} { background-image: url(${source.srcSet['3x']}); }`);
2224
return acc;
2325
},
2426
{ '1x': [], '2x': [], '3x': [] },
2527
);
2628

2729
return `
28-
${result['1x'].join(' ')}
29-
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { ${result['2x'].join(' ')} }
30-
@media (-webkit-min-device-pixel-ratio: 3), (min-resolution: 288dpi) { ${result['3x'].join(' ')} }
30+
${result['1x'].join(' ')}
31+
${
32+
result['2x'].length
33+
? `@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { ${result['2x'].join(
34+
' ',
35+
)} }`
36+
: ''
37+
}
38+
${
39+
result['3x'].length
40+
? ` @media (-webkit-min-device-pixel-ratio: 3), (min-resolution: 288dpi) { ${result[
41+
'3x'
42+
].join(' ')} }`
43+
: ''
44+
}
3145
`;
3246
};
3347

src/utils/getCompressionRatio.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Dpr, CompressionRatio } from '../types';
2+
3+
export const getCompressionRatio = (pixelRatios: Dpr[]): CompressionRatio => {
4+
const length = pixelRatios.length;
5+
6+
return pixelRatios.reduce((acc, item, index) => {
7+
if (index + 1 === length) {
8+
acc[item] = 0;
9+
return acc;
10+
}
11+
12+
acc[item] = Number(((index + 1) / length).toFixed(5));
13+
return acc;
14+
}, {} as CompressionRatio);
15+
};

0 commit comments

Comments
 (0)