Add resized-image support and add example

This commit is contained in:
Jinksi 2017-11-12 14:36:06 +10:00
parent 2b124b9b08
commit 4cbab9c5ce
7 changed files with 313 additions and 12 deletions

View file

@ -0,0 +1,83 @@
const fs = require('fs')
const path = require('path')
const globCb = require('glob')
const util = require('util')
const sharp = require('sharp')
const glob = util.promisify(globCb)
const readFile = util.promisify(fs.readFile)
const options = {
inputDir: './public/images/uploads',
outputDir: './public/images/uploads/resized',
sizes: [300, 600, 1200, 1800],
imageFormats: ['jpg', 'jpeg', 'png', 'gif', 'webp']
}
const saveImage = ({ buffer, size, outputFile }) => {
return new Promise((resolve, reject) => {
sharp(buffer)
.resize(size)
.toFile(outputFile, err => {
if (err) {
return reject(err)
} else {
return resolve(console.log(`✅ Saved ${outputFile}`))
}
})
})
}
const saveImages = ({ buffer, filename }) => {
console.log(`🎞 Processing ${filename}`)
return Promise.all(
options.sizes.map(async size => {
const extname = path.extname(filename)
const newFilename = `${path.basename(
filename,
extname
)}.${size}${extname}`
const outputFile = `${options.outputDir}/${newFilename}`
const fileExists = await doesFileExist({ filename: outputFile })
if (fileExists) return console.log(`↩️ ${outputFile} exists, skipping`)
return saveImage({ buffer, size, outputFile })
})
)
}
const readFiles = files =>
Promise.all(
files.map(async filename => {
const buffer = await readFile(filename)
return { filename, buffer }
})
)
const doesFileExist = async ({ filename }) => {
try {
await readFile(filename)
return true
} catch (e) {
return false
}
}
const resizeImages = async () => {
console.log(`✨ Reading image files in ${options.inputDir}`)
try {
const fileGlob = `${options.inputDir}/**/**.+(${options.imageFormats.join(
'|'
)})`
const files = await glob(fileGlob)
const ignore = new RegExp(
`(${options.sizes.join('|')}).(${options.imageFormats.join('|')})$`
)
const filesToResize = files.filter(filename => !filename.match(ignore))
const imageFiles = await readFiles(filesToResize)
imageFiles.map(saveImages)
} catch (e) {
console.log(e)
}
}
resizeImages()

View file

@ -16,6 +16,7 @@
"gray-matter": "^3.1.1",
"js-yaml": "^3.10.0",
"react-scripts": "^1.0.10",
"sharp": "^0.18.4",
"snazzy": "^7.0.0",
"standard": "^10.0.2",
"sw-precache": "^5.2.0"
@ -32,16 +33,17 @@
"styled-components": "^2.1.0"
},
"scripts": {
"start": "npm run parse-content && react-scripts start",
"build": "npm run parse-content && react-scripts build && react-snapshot && npm run sw",
"start":
"npm run parse-content && npm run resize-images && react-scripts start",
"build":
"npm run parse-content && npm run resize-images && react-scripts build && react-snapshot && npm run sw",
"parse-content": "node ./functions/parse-content.js",
"resize-images": "node ./functions/resize-images.js",
"sw": "sw-precache --config='sw-precache-config.js'",
"test": "standard | snazzy && react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"reactSnapshot": {
"include": [
"/404"
]
"include": ["/404"]
}
}

View file

@ -40,6 +40,7 @@ collections: # A list of collections the CMS should be able to edit
fields:
- {label: Title, name: title, widget: string}
- {label: Subtitle, name: subtitle, widget: string}
- {label: Featured Image, name: featuredImage, widget: image}
- {label: Section 1, name: section1, widget: markdown}
- {label: Section 2, name: section2, widget: markdown}
- file: "content/pages/contact.json"

View file

@ -1,8 +1,9 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { Section, Container } from './common'
import { Section, Container, BackgroundImage } from './common'
import { getImageSrc } from '../util/getImageUrl'
import { color } from '../globalStyles'
const Header = styled(Section)`
@ -10,14 +11,21 @@ const Header = styled(Section)`
color: ${color.primary};
background: ${color.primary};
color: white;
h2{
h2 {
font-weight: 200;
}
`
const PageHeader = ({ title, subtitle }) => (
<Header>
<Container>
const PageHeader = ({ title, subtitle, backgroundImage }) => (
<Header relative>
{backgroundImage && (
<BackgroundImage
image={getImageSrc(backgroundImage, '1200')}
opacity={0.5}
/>
)}
<Container relative>
<h1>{title}</h1>
{subtitle ? <h2>{subtitle}</h2> : ''}
</Container>

43
src/util/getImageUrl.js Normal file
View file

@ -0,0 +1,43 @@
const sizes = [300, 600, 1200, 1800]
const outputDir = '/images/uploads/'
const resizedDir = '/images/uploads/resized/'
const getImageSrcset = path => {
if (path.indexOf('http') >= 0) {
return console.warn('Cannot get srcset for external image: ' + path)
}
const filename = path.split('.').shift()
const extname = path.split('.').pop()
const pathname = encodeURI(filename.replace(outputDir, resizedDir))
const srcset = sizes
.map(size => `${pathname}.${size}.${extname} ${size}w`)
.join(', ')
return srcset
}
const getImageSrc = (path, sizeRequested) => {
if (path.indexOf('http') >= 0) return path
sizeRequested = parseInt(sizeRequested, 10)
let size
if (sizeRequested) {
// rounds up to nearest size or returns largest
size =
sizes.filter(num => num >= sizeRequested)[0] || sizes[sizes.length - 1]
} else {
// get the middle size
size = sizes[Math.ceil(sizes.length / 2)]
}
const extname = path.split('.').pop()
const filename = path.split('.').shift()
const pathname = encodeURI(filename.replace(outputDir, resizedDir))
return `${pathname}.${size}.${extname}`
}
module.exports = {
getImageSrcset,
getImageSrc,
sizes,
outputDir
}

View file

@ -11,7 +11,11 @@ export default ({ page }) => (
<Helmet>
<title>{page.title}</title>
</Helmet>
<PageHeader title={page.title} subtitle={page.subtitle} />
<PageHeader
title={page.title}
subtitle={page.subtitle}
backgroundImage={page.featuredImage}
/>
<Section thin>
<Container>
<Marked source={page.section1} />

162
yarn.lock
View file

@ -1398,6 +1398,15 @@ caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
caw@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95"
dependencies:
get-proxy "^2.0.0"
isurl "^1.0.0-alpha5"
tunnel-agent "^0.6.0"
url-to-options "^1.0.1"
center-align@^0.1.1:
version "0.1.3"
resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
@ -1438,6 +1447,10 @@ chokidar@^1.6.0, chokidar@^1.7.0:
optionalDependencies:
fsevents "^1.0.0"
chownr@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181"
ci-info@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.0.0.tgz#dc5285f2b4e251821683681c381c3388f46ec534"
@ -1524,6 +1537,12 @@ color-convert@^1.0.0, color-convert@^1.3.0, color-convert@^1.9.0:
dependencies:
color-name "^1.1.1"
color-convert@^1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed"
dependencies:
color-name "^1.1.1"
color-name@^1.0.0, color-name@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689"
@ -1534,6 +1553,13 @@ color-string@^0.3.0:
dependencies:
color-name "^1.0.0"
color-string@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.2.tgz#26e45814bc3c9a7cbd6751648a41434514a773a9"
dependencies:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
color@^0.11.0:
version "0.11.4"
resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764"
@ -1542,6 +1568,13 @@ color@^0.11.0:
color-convert "^1.3.0"
color-string "^0.3.0"
color@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/color/-/color-2.0.1.tgz#e4ed78a3c4603d0891eba5430b04b86314f4c839"
dependencies:
color-convert "^1.9.1"
color-string "^1.5.2"
colormin@^1.0.5:
version "1.1.2"
resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133"
@ -1617,6 +1650,13 @@ concat-stream@^1.5.0, concat-stream@^1.5.2, concat-stream@^1.6.0:
readable-stream "^2.2.2"
typedarray "^0.0.6"
config-chain@^1.1.11:
version "1.1.11"
resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2"
dependencies:
ini "^1.3.4"
proto-list "~1.2.1"
configstore@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/configstore/-/configstore-2.1.0.tgz#737a3a7036e9886102aa6099e47bb33ab1aba1a1"
@ -1954,6 +1994,12 @@ decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
decompress-response@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
dependencies:
mimic-response "^1.0.0"
deep-equal@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
@ -2053,6 +2099,10 @@ detect-indent@^4.0.0:
dependencies:
repeating "^2.0.0"
detect-libc@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-0.2.0.tgz#47fdf567348a17ec25fcbf0b9e446348a76f9fb5"
detect-node@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127"
@ -3137,6 +3187,12 @@ get-caller-file@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
get-proxy@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93"
dependencies:
npm-conf "^1.1.0"
get-stdin@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
@ -3340,6 +3396,16 @@ has-flag@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
has-symbol-support-x@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.1.tgz#66ec2e377e0c7d7ccedb07a3a84d77510ff1bc4c"
has-to-string-tag-x@^1.2.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d"
dependencies:
has-symbol-support-x "^1.4.1"
has-unicode@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@ -3703,6 +3769,10 @@ is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
is-arrayish@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.1.tgz#c2dfc386abaa0c3e33c48db3fe87059e69065efd"
is-binary-path@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
@ -3810,6 +3880,10 @@ is-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
is-object@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470"
is-path-cwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
@ -4015,6 +4089,13 @@ istanbul-reports@^1.1.0:
dependencies:
handlebars "^4.0.3"
isurl@^1.0.0-alpha5:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67"
dependencies:
has-to-string-tag-x "^1.2.0"
is-object "^1.0.1"
jest-changed-files@^20.0.3:
version "20.0.3"
resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-20.0.3.tgz#9394d5cc65c438406149bef1bf4d52b68e03e3f8"
@ -4724,6 +4805,10 @@ mimic-fn@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18"
mimic-response@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e"
minimalistic-assert@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"
@ -4752,6 +4837,18 @@ minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
minipass@^2.0.2, minipass@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.2.1.tgz#5ada97538b1027b4cf7213432428578cb564011f"
dependencies:
yallist "^3.0.0"
minizlib@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.0.4.tgz#8ebb51dd8bbe40b0126b5633dbb36b284a2f523c"
dependencies:
minipass "^2.2.1"
mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
@ -4789,6 +4886,10 @@ nan@^2.3.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.5.1.tgz#d5b01691253326a97a2bbee9e61c55d8d60351e2"
nan@^2.6.2:
version "2.7.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.7.0.tgz#d95bf721ec877e08db276ed3fc6eb78f9083ad46"
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@ -4916,6 +5017,13 @@ normalize-url@^1.4.0:
query-string "^4.1.0"
sort-keys "^1.0.0"
npm-conf@^1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9"
dependencies:
config-chain "^1.1.11"
pify "^3.0.0"
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@ -5000,7 +5108,7 @@ once@^1.3.0:
dependencies:
wrappy "1"
once@^1.3.3, once@^1.4.0:
once@^1.3.1, once@^1.3.3, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
dependencies:
@ -5677,6 +5785,10 @@ prop-types@^15.6.0:
loose-envify "^1.3.1"
object-assign "^4.1.1"
proto-list@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
proxy-addr@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3"
@ -6451,6 +6563,18 @@ shallowequal@^0.2.2:
dependencies:
lodash.keys "^3.1.2"
sharp@^0.18.4:
version "0.18.4"
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.18.4.tgz#fe329c0f06896c28aa24376df1fff02ae57f2d34"
dependencies:
caw "^2.0.0"
color "^2.0.0"
detect-libc "^0.2.0"
nan "^2.6.2"
semver "^5.3.0"
simple-get "^2.7.0"
tar "^3.1.5"
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@ -6486,6 +6610,24 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
simple-concat@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6"
simple-get@^2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.7.0.tgz#ad37f926d08129237ff08c4f2edfd6f10e0380b5"
dependencies:
decompress-response "^3.3.0"
once "^1.3.1"
simple-concat "^1.0.0"
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
dependencies:
is-arrayish "^0.3.1"
slash@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
@ -6919,6 +7061,16 @@ tar@^2.2.1:
fstream "^1.0.2"
inherits "2"
tar@^3.1.5:
version "3.2.1"
resolved "https://registry.yarnpkg.com/tar/-/tar-3.2.1.tgz#9aa8e41c88f09e76c166075bc71f93d5166e61b1"
dependencies:
chownr "^1.0.1"
minipass "^2.0.2"
minizlib "^1.0.3"
mkdirp "^0.5.0"
yallist "^3.0.2"
test-exclude@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.0.tgz#04ca70b7390dd38c98d4a003a173806ca7991c91"
@ -7161,6 +7313,10 @@ url-parse@^1.1.8:
querystringify "~1.0.0"
requires-port "1.0.x"
url-to-options@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9"
url@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
@ -7490,6 +7646,10 @@ yallist@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.0.0.tgz#306c543835f09ee1a4cb23b7bce9ab341c91cdd4"
yallist@^3.0.0, yallist@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9"
yargs-parser@^4.2.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c"