├── .eslintignore
├── .eslintrc
├── .gitignore
├── .npmignore
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── examples
└── basic
│ ├── index.html
│ ├── index.js
│ ├── package.json
│ ├── server.js
│ └── webpack.config.js
├── lib
├── components
│ ├── BaseImage.js
│ └── Image.js
├── index.js
└── utils.js
├── package.json
├── test
├── client
│ └── image.js
├── misc
│ └── utils.js
└── server
│ └── image.js
└── webpack.config.js
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | src
3 | ./**/*/node_modules
4 | dist
5 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./node_modules/lab/lib/linters/eslint/.eslintrc",
3 | "ecmaFeatures": {
4 | "jsx": true,
5 | "arrowFunctions": true,
6 | },
7 | "env": {
8 | "node": true,
9 | "browser": true
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependency directory
2 | node_modules
3 |
4 | # Users Environment Variables
5 | .lock-wscript
6 |
7 | # Distribution does not belong in repo
8 | dist
9 |
10 | coverage.html
11 | npm-debug.log
12 | src
13 |
14 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | webpack.config.js
2 | scripts
3 | examples
4 | .travis.yml
5 | lib
6 |
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - "0.10"
5 | - "0.12"
6 | - "iojs"
7 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## v0.0.4 (Upcoming)
2 | - Get to 100% test coverage
3 |
4 | ## v0.0.3
5 | - update to react 0.13
6 | - simplify codebase
7 | - ensure test infrastructure is properly set up with recent changes
8 | - rename .js to .jsx for components
9 | - npm prepublish step
10 |
11 | ## v0.0.2
12 | - debounce method on resize events of 150ms
13 | - fix bug in renderNative where src attribute would show the srcset information
14 | - some internal reordering based on initial test framework
15 |
16 | ## v0.0.1
17 | - Initial implement of Image component
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Lois Desplat
4 |
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:
11 |
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.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-picture
2 | [](https://travis-ci.org/ldesplat/react-picture)
3 |
4 | ## This component is not maintained anymore but its source code may be of use to some people
5 |
6 | You should take a look at https://github.com/reacttraining/react-media as an example on how the React community has been able to make a more abstracted version of this very same concept. As before, you should also check the Alternative Libraries section below for some more inspiration.
7 |
8 | ## Description
9 |
10 | React component for rendering responsive images. Attempts to implement `
` support in non-compliant browsers, otherwize renders the native `
`. Will eventually support Picture & Source elements.
11 |
12 | ## How to use
13 |
14 | ```npm install react-picture```
15 |
16 | Then use in your react app like so:
17 |
18 | ```
19 | var Img = require('react-picture').Image;
20 | ...
21 | render: function() {
22 | var imgs = '//placebacon.net/200/150 600w, //placebacon.net/300/300 800w';
23 |
24 | return (
25 |
26 | );
27 | }
28 | ...
29 | ```
30 |
31 | The following properties can be passed to the Image component:
32 | - `alt` - Required and describes your picture
33 | - `srcSet` - Required and consists of a string formated like srcset
34 | - `extra` - Optional object which contains properties that will be put on img tag
35 |
36 | ## Features
37 |
38 | - Use `
` when supported
39 | - Implement srcset support for browsers that do not have it, using javascript. Currently missing sizes implementation.
40 |
41 | ## Roadmap
42 |
43 | ### 0.1.0
44 | - Implement sizes attribute
45 |
46 | ### 1.0
47 | - Stable API
48 | - Correct implementation of match method
49 | - ~~Verify srcset feature detection~~
50 | - ie8 & up browser support (w/React polyfills only)
51 | - Performance optimizations
52 | - ~~Ismorphic support~~
53 | - 100% test coverage
54 | - ~~Travis CI~~
55 |
56 | ### To be discussed
57 | - PictureContainer
58 | - Karma tests
59 |
60 | ### 2.0
61 | - Picture element
62 | - Source element
63 |
64 | ## References
65 |
66 | - [The picture element](http://www.w3.org/html/wg/drafts/html/master/embedded-content.html#the-picture-element)
67 | - [The img element](http://www.w3.org/html/wg/drafts/html/master/embedded-content.html#the-img-element)
68 |
69 | ## Alternative libraries
70 |
71 | - If you are not using react in your app, [BBC-News/Imager.js](https://github.com/BBC-News/Imager.js) is a very good library
72 | - srcset polyfill [borismus/srcset-polyfill](https://github.com/borismus/srcset-polyfill)
73 | - picture polyfill [scottjehl/picturefill](https://github.com/scottjehl/picturefill)
74 |
75 | ## Acknowledgements
76 |
77 | - React's excellent library & documentation
78 | - Ryan Florence's components on github which were stolen to start up (webpack setup, browserify, scripts)
79 | - [This excellent article](http://www.html5rocks.com/en/mobile/high-dpi/)
80 |
--------------------------------------------------------------------------------
/examples/basic/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | react-picture example
4 |
5 |
6 | react-picture
7 | Response images using React
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/basic/index.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var RP = require('react-picture');
3 |
4 | var App = React.createClass({
5 |
6 | imgs: [
7 | '//placebacon.net/200/150 600w',
8 | '//placebacon.net/300/300 800w',
9 | '//placebacon.net/400/400 1000w'
10 | ],
11 |
12 | render: function () {
13 |
14 | return (
15 |
16 |
17 |
18 |
19 |
20 | );
21 | }
22 |
23 | });
24 |
25 | React.render(, document.getElementById('root'));
26 |
--------------------------------------------------------------------------------
/examples/basic/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-picture-example",
3 | "version": "1.0.0",
4 | "description": "react-picture-example-description",
5 | "main": "server.js",
6 | "scripts": {
7 | "start": "node server.js"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/ldesplat/react-picture.git"
12 | },
13 | "keywords": [
14 | "react-picture-keywords"
15 | ],
16 | "license": "MIT",
17 | "bugs": {
18 | "url": "https://github.com/ldesplat/react-picture/issues"
19 | },
20 | "homepage": "https://github.com/ldesplat/react-picture",
21 | "dependencies": {
22 | "react": "^0.13.3"
23 | },
24 | "devDependencies": {
25 | "babel-core": "^5.6.18",
26 | "babel-loader": "^5.1.4",
27 | "node-libs-browser": "^0.5.2",
28 | "react-hot-loader": "^1.2.7",
29 | "webpack": "^1.9.11",
30 | "webpack-dev-server": "^1.9.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/examples/basic/server.js:
--------------------------------------------------------------------------------
1 | var Webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var Config = require('./webpack.config');
4 |
5 | new WebpackDevServer(Webpack(Config), {
6 | publicPath: Config.output.publicPath,
7 | hot: true,
8 | historyApiFallback: true,
9 | stats: {
10 | colors: true
11 | }
12 | }).listen(3000, 'localhost', function (err) {
13 |
14 | if (err) {
15 | console.log(err);
16 | }
17 |
18 | console.log('Listening at localhost:3000');
19 | });
20 |
--------------------------------------------------------------------------------
/examples/basic/webpack.config.js:
--------------------------------------------------------------------------------
1 | var Path = require('path');
2 | var Webpack = require('webpack');
3 |
4 | module.exports = {
5 | devtool: 'eval',
6 | entry: [
7 | 'webpack-dev-server/client?http://localhost:3000',
8 | 'webpack/hot/only-dev-server',
9 | './index'
10 | ],
11 | output: {
12 | path: Path.join(__dirname, 'dist'),
13 | filename: 'bundle.js',
14 | publicPath: '/static/'
15 | },
16 | plugins: [
17 | new Webpack.HotModuleReplacementPlugin(),
18 | new Webpack.NoErrorsPlugin()
19 | ],
20 | resolve: {
21 | alias: {
22 | 'react-picture': Path.join(__dirname, '..', '..', 'lib')
23 | },
24 | extensions: ['', '.js']
25 | },
26 | module: {
27 | loaders: [{
28 | test: /\.js$/,
29 | loaders: ['react-hot', 'babel'],
30 | exclude: /node_modules/,
31 | include: __dirname
32 | }, {
33 | test: /\.js$/,
34 | loaders: ['babel'],
35 | include: Path.join(__dirname, '..', '..', 'lib')
36 | }]
37 | }
38 | };
39 |
--------------------------------------------------------------------------------
/lib/components/BaseImage.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var Utils = require('../utils');
3 |
4 |
5 | /** Equivalent to html
element
6 | *
7 | *
8 | */
9 | var BaseImageComponent = module.exports = React.createClass({
10 |
11 |
12 | propTypes: {
13 | srcSet: React.PropTypes.string.isRequired,
14 | alt: React.PropTypes.string.isRequired,
15 | extra: React.PropTypes.object,
16 | nativeSupport: React.PropTypes.string
17 | },
18 |
19 |
20 | getDefaultProps: function () {
21 |
22 | return {
23 | extra: {},
24 | nativeSupport: 'none'
25 | };
26 | },
27 |
28 |
29 | getInitialState: function () {
30 |
31 | return {
32 | w: Utils.getWidth(),
33 | x: Utils.getDensity()
34 | };
35 | },
36 |
37 |
38 | componentDidMount: function () {
39 |
40 | if (this.props.nativeSupport !== 'full') {
41 | window.addEventListener('resize', this.resizeThrottler, false);
42 | }
43 | },
44 |
45 |
46 | componentWillUnmount: function () {
47 |
48 | if (!this.props.nativeSupport !== 'full') {
49 | window.removeEventListener('resize', this.resizeThrottler, false);
50 | }
51 | },
52 |
53 |
54 | render: function () {
55 |
56 | if (!this.props.srcSet) {
57 | return null;
58 | }
59 |
60 | var candidates = BaseImageComponent._buildCandidates(this.props.srcSet);
61 |
62 | if (this.props.nativeSupport === 'full') {
63 | return this.renderNative(candidates);
64 | }
65 |
66 | return (
67 |
68 | );
69 | },
70 |
71 |
72 | renderNative: function (candidates) {
73 |
74 | return (
75 |
76 | );
77 | },
78 |
79 |
80 | // Taken from https://developer.mozilla.org/en-US/docs/Web/Events/resize
81 | resizing: false,
82 | resizeThrottler: function () {
83 |
84 | if (!this.resizing) {
85 | this.resizing = true;
86 |
87 | if (window && window.requestAnimationFrame) {
88 | window.requestAnimationFrame(this.onResize);
89 | } else {
90 | setTimeout(this.onResize, 66);
91 | }
92 | }
93 | },
94 |
95 |
96 | onResize: function () {
97 |
98 | this.setState({ w: Utils.getWidth(), x: Utils.getDensity() });
99 | this.resizing = false;
100 | },
101 |
102 |
103 | statics: {
104 |
105 | _buildCandidates: function (srcset) {
106 |
107 | return srcset.split(',').map(function (srcImg) {
108 |
109 | var stringComponents = srcImg.trim().split(' ');
110 | var candidate = {
111 | url: stringComponents[0].trim(),
112 | w: 0,
113 | x: 1.0
114 | };
115 |
116 | for (var i = 1; i < stringComponents.length; i++) {
117 | var str = stringComponents[i].trim();
118 | if (str.indexOf('w', str.length - 1) !== -1) {
119 | candidate.w = parseInt(str.substring(0, str.length - 1));
120 | } else if (str.indexOf('x', str.length - 1) !== -1) {
121 | candidate.x = parseFloat(str.substring(0, str.length - 1));
122 | } else {
123 | console.warn('Invalid parameter passed to Image srcSet: [' + str + '] in ' + srcImg);
124 | }
125 | }
126 |
127 | return candidate;
128 | });
129 | },
130 |
131 |
132 | __compare: function (a, b, state, accessorFn) {
133 |
134 | var aDt = accessorFn(a) - state;
135 | var bDt = accessorFn(b) - state;
136 |
137 | if ((aDt === 0 && bDt !== 0) || // a perfectly matches target but b does not
138 | (bDt < 0 && aDt >= 0)) // b is less than target but a is the same or better
139 | {
140 | return a;
141 | }
142 |
143 | if ((bDt === 0 && aDt !== 0) || // b perfectly matches target but a does not
144 | (aDt < 0 && bDt >= 0)) // a is less than target but b is the same or better
145 | {
146 | return b;
147 | }
148 |
149 | if (Math.abs(aDt) < Math.abs(bDt))
150 | {
151 | return a;
152 | }
153 |
154 | if (Math.abs(bDt) < Math.abs(aDt))
155 | {
156 | return b;
157 | }
158 |
159 | return a;
160 | },
161 |
162 |
163 | _matchImage: function (candidates, width, density) {
164 |
165 | if (!candidates || candidates.length === 0) {
166 | return null;
167 | }
168 |
169 | var image = candidates.reduce(function (a, b) {
170 |
171 | if (a.x === b.x) {
172 | // Both have the same density so attempt to find a better one using width
173 | if (a.w === b.w) {
174 | return a; // hey, it came first!
175 | }
176 |
177 | return BaseImageComponent.__compare(a, b, width, img => img.w);
178 | }
179 |
180 | return BaseImageComponent.__compare(a, b, density, img => img.x);
181 | }).url;
182 |
183 | return image;
184 | }
185 | }
186 | });
187 |
--------------------------------------------------------------------------------
/lib/components/Image.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var BaseImage = require('./BaseImage');
3 |
4 |
5 | /** Equivalent to html
element
6 | *
7 | *
8 | */
9 | var ImageComponent = module.exports = React.createClass({
10 |
11 |
12 | propTypes: {
13 | srcSet: React.PropTypes.string.isRequired,
14 | alt: React.PropTypes.string.isRequired,
15 | extra: React.PropTypes.object,
16 | nativeSupport: React.PropTypes.string
17 | },
18 |
19 |
20 | getDefaultProps: function () {
21 | // Calculate nativeSupport in getDefaultProps so we don't
22 | // check this everytime the component is mounted despite
23 | // making it much harder for testing
24 | var nativeSupport = 'full';
25 | if (typeof document !== 'undefined') {
26 | var img = document.createElement('img');
27 | ('srcset' in img) ? nativeSupport = 'partial' : nativeSupport = 'none';
28 | (nativeSupport === 'partial' && 'sizes' in img) ? nativeSupport = 'full' : nativeSupport = 'partial';
29 | }
30 |
31 | return {
32 | extra: {},
33 | nativeSupport: nativeSupport
34 | };
35 | },
36 |
37 |
38 | render: function () {
39 |
40 | return ;
41 | }
42 | });
43 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | module.exports.BaseImage = require('./components/BaseImage');
2 | module.exports.Image = require('./components/Image');
3 | //module.exports.Picture= require('./components/Picture');
4 |
--------------------------------------------------------------------------------
/lib/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 |
4 | module.exports.getWidth = function () {
5 |
6 | if (typeof window !== 'undefined') {
7 | return window.innerWidth || document.documentElement.clientWidth;
8 | }
9 |
10 | return 0;
11 | };
12 |
13 |
14 | module.exports.getDensity = function () {
15 |
16 | if (typeof window !== 'undefined') {
17 | return window.devicePixelRatio || 1;
18 | }
19 |
20 | return 1;
21 | };
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-picture",
3 | "version": "0.0.4",
4 | "description": "Responsive images component for React.JS",
5 | "main": "./src/index",
6 | "scripts": {
7 | "clean": "rimraf src dist",
8 | "build": "babel -d src/ lib/",
9 | "build:umd": "webpack lib/index.js dist/react-picture.js && NODE_ENV=production webpack lib/index.js dist/react-picture.min.js",
10 | "test": "lab -S -L -T node_modules/lab-babel -t 70",
11 | "test-cov-html": "lab -c -S -T node_modules/lab-babel -r html -o coverage.html",
12 | "prepublish": "npm run test && npm run clean && npm run build && npm run build:umd"
13 | },
14 | "repository": {
15 | "type": "git",
16 | "url": "https://github.com/ldesplat/react-picture.git"
17 | },
18 | "keywords": [
19 | "image",
20 | "picture",
21 | "responsive",
22 | "srcset",
23 | "react",
24 | "react-component"
25 | ],
26 | "author": "Lois Desplat",
27 | "license": "MIT",
28 | "bugs": {
29 | "url": "https://github.com/ldesplat/react-picture/issues"
30 | },
31 | "homepage": "https://github.com/ldesplat/react-picture",
32 | "devDependencies": {
33 | "babel": "5.x.x",
34 | "babel-core": "5.x.x",
35 | "babel-loader": "5.x.x",
36 | "code": "1.x.x",
37 | "lab": "5.x.x",
38 | "lab-babel": "1.x.x",
39 | "react": "0.13.x",
40 | "rimraf": "^2.4.3",
41 | "webpack": "1.x.x",
42 | "webpack-dev-server": "1.x.x"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/test/client/image.js:
--------------------------------------------------------------------------------
1 | /*var React = require('react/addons');
2 | var Code = require('code');
3 | var Lab = require('lab');
4 |
5 | // Test shortcuts
6 | var lab = exports.lab = Lab.script();
7 |
8 | var expect = Code.expect;
9 | var before = lab.before;
10 | var after = lab.after;
11 | var beforeEach = lab.beforeEach;
12 | var afterEach = lab.afterEach;
13 | var describe = lab.experiment;
14 | var it = lab.test;
15 |
16 | var Img = require('../../lib/index').Image;
17 |
18 |
19 | var internals = {
20 | sampleSrcSet: 'http://fancyserver.com/image.jpg 600w, http://fancyserver.com/image2.jpg 1000w'
21 | };
22 |
23 |
24 | internals.exDOM = function () {
25 |
26 | return document.getElementById('example');
27 | };
28 |
29 |
30 | describe('JSDOM - Native -', function () {
31 |
32 | before(function (done) {
33 |
34 | document.createElement = function (name) {
35 |
36 | var element = Object.getPrototypeOf(this).createElement.call(this);
37 | if (name === 'img') {
38 | element.srcset = '';
39 | }
40 |
41 | return element;
42 | };
43 |
44 | done();
45 | });
46 |
47 |
48 | after(function (done) {
49 |
50 | document.createElement = function (name) {
51 |
52 | return Object.getPrototypeOf(this).createElement.call(this);
53 | };
54 |
55 | done();
56 | });
57 |
58 | afterEach(function (done) {
59 |
60 | React.unmountComponentAtNode(internals.exDOM());
61 | done();
62 | });
63 |
64 |
65 | it('renders a null image', function (done) {
66 |
67 | React.render(
, internals.exDOM());
68 | expect(internals.exDOM().innerHTML).to.not.contain('img');
69 | done();
70 | });
71 |
72 |
73 | it('render a proper image', function (done) {
74 |
75 | React.render(
, internals.exDOM());
76 | var html = internals.exDOM().innerHTML;
77 |
78 | expect(html).to.contain('alt="text"');
79 | expect(html).to.contain('src="http://fancyserver.com/image.jpg"');
80 | expect(html).to.contain('srcset="http://fancyserver.com/image.jpg 600w, http://fancyserver.com/image2.jpg 1000w"');
81 | done();
82 | });
83 | });
84 |
85 | describe('JSDOM - Not native -', function () {
86 |
87 | afterEach(function (done) {
88 |
89 | React.unmountComponentAtNode(internals.exDOM());
90 | done();
91 | });
92 |
93 |
94 | it('renders a null image', function (done) {
95 |
96 | React.render(
, internals.exDOM());
97 | expect(internals.exDOM().innerHTML).to.not.contain('img');
98 | done();
99 | });
100 |
101 |
102 | it('render a proper image', function (done) {
103 |
104 | React.render(
, internals.exDOM());
105 | var html = internals.exDOM().innerHTML;
106 |
107 | expect(html).to.contain('alt="text"');
108 | expect(html).to.contain('src="http://fancyserver.com/image2.jpg"');
109 | expect(html).to.not.contain('srcset');
110 | done();
111 | });
112 |
113 | });
114 | */
115 |
--------------------------------------------------------------------------------
/test/misc/utils.js:
--------------------------------------------------------------------------------
1 | var Code = require('code');
2 | var Lab = require('lab');
3 |
4 | // Test shortcuts
5 | var lab = exports.lab = Lab.script();
6 |
7 | var expect = Code.expect;
8 | var describe = lab.experiment;
9 | var it = lab.test;
10 |
11 | var Utils = require('../../lib/utils');
12 |
13 | describe('Utils methods -', function () {
14 |
15 | it('gets width', function (done) {
16 |
17 | var width = Utils.getWidth();
18 | expect(width).to.equal(0);
19 | done();
20 | });
21 |
22 | it('gets density', function (done) {
23 |
24 | var density = Utils.getDensity();
25 | expect(density).to.equal(1);
26 | done();
27 | });
28 |
29 | it('gets width with document.documentElement', function (done) {
30 |
31 | global.window = {};
32 | global.document = {
33 | documentElement: {
34 | clientWidth: 1024
35 | }
36 | };
37 |
38 | var width = Utils.getWidth();
39 |
40 | delete global.window;
41 | delete global.document;
42 |
43 | expect(width).to.equal(1024);
44 | done();
45 | });
46 |
47 | it('gets width with window.innerWidth', function (done) {
48 |
49 | global.window = {
50 | innerWidth: 256
51 | };
52 |
53 | var width = Utils.getWidth();
54 |
55 | delete global.window;
56 |
57 | expect(width).to.equal(256);
58 | done();
59 | });
60 |
61 |
62 | it('gets density with window.devicePixelRatio', function (done) {
63 |
64 | global.window = {
65 | devicePixelRatio: 2
66 | };
67 |
68 | var density = Utils.getDensity();
69 |
70 | delete global.window;
71 |
72 | expect(density).to.equal(2);
73 | done();
74 | });
75 |
76 | it('gets density with window but no devicePixelRatio', function (done) {
77 |
78 | global.window = {};
79 |
80 | var density = Utils.getDensity();
81 |
82 | delete global.window;
83 |
84 | expect(density).to.equal(1);
85 | done();
86 | });
87 | });
88 |
--------------------------------------------------------------------------------
/test/server/image.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var Code = require('code');
3 | var Lab = require('lab');
4 |
5 |
6 | // Test shortcuts
7 | var lab = exports.lab = Lab.script();
8 | var expect = Code.expect;
9 | var describe = lab.experiment;
10 | var it = lab.test;
11 |
12 |
13 | var internals = {
14 | sampleSrcSet: 'http://fancyserver.com/image.jpg 600w, http://fancyserver.com/image2.jpg 1000w',
15 | nativeOutput: '
',
16 | renderOutput: '
'
17 | };
18 |
19 |
20 | var Img = require('../../lib/index').Image;
21 |
22 |
23 | describe('Image Component - Testing as NodeJS', function () {
24 |
25 | it('uses default native support', function (done) {
26 |
27 | var img = React.renderToStaticMarkup(
28 |
29 | );
30 |
31 | expect(img).to.equal(internals.nativeOutput);
32 |
33 | done();
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Webpack = require('webpack');
4 |
5 | var plugins = [
6 | new Webpack.optimize.OccurenceOrderPlugin(),
7 | new Webpack.DefinePlugin({
8 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
9 | })
10 | ];
11 |
12 | if (process.env.NODE_ENV === 'production') {
13 | plugins.push(
14 | new Webpack.optimize.UglifyJsPlugin({
15 | compressor: {
16 | 'screw_ie8': true,
17 | warnings: false
18 | }
19 | })
20 | );
21 | }
22 |
23 | module.exports = {
24 | module: {
25 | loaders: [{
26 | test: /\.js$/,
27 | loaders: ['babel-loader'],
28 | exclude: /node_modules/
29 | }]
30 | },
31 | output: {
32 | library: 'react-picture',
33 | libraryTarget: 'umd'
34 | },
35 | plugins: plugins,
36 | resolve: {
37 | extensions: ['', '.js']
38 | }
39 | };
40 |
--------------------------------------------------------------------------------