Permalink
Please sign in to comment.
Showing
with
2,160 additions
and 1 deletion.
- +3 โ0 .gitignore
- +3 โ1 README.md
- +37 โ0 helper.js
- +43 โ0 index.js
- +29 โ0 package.json
- +15 โ0 svg.js
- +2,030 โ0 yarn.lock
| @@ -0,0 +1,3 @@ | ||
| +node_modules | ||
| +*.log | ||
| +test.html |
| @@ -1 +1,3 @@ | ||
| -# avatar | ||
| +# avatar | ||
| + | ||
| +Avatar as a microservice generates beautiful generated avatars for your app or homepage. |
| @@ -0,0 +1,37 @@ | ||
| +function djb2(str) { | ||
| + let hash = 5381 | ||
| + for (let i = 0; i < str.length; i++) { | ||
| + hash = ((hash << 5) + hash) + str.charCodeAt(i) | ||
| + } | ||
| + return hash | ||
| +} | ||
| + | ||
| +function shouldChangeColor(color) { | ||
| + const rgb = color.rgb().array() | ||
| + const val = 765 - (rgb[0] + rgb[1] + rgb[2]) | ||
| + if (val < 250) { | ||
| + return true | ||
| + } | ||
| + return false | ||
| +} | ||
| + | ||
| +exports.hashStringToColor = function (str) { | ||
| + const hash = djb2(str) | ||
| + const r = (hash & 0xFF0000) >> 16 | ||
| + const g = (hash & 0x00FF00) >> 8 | ||
| + const b = hash & 0x0000FF | ||
| + return '#' + ('0' + r.toString(16)).substr(-2) + ('0' + g.toString(16)).substr(-2) + ('0' + b.toString(16)).substr(-2) | ||
| +} | ||
| + | ||
| +exports.getMatchingColor = function (firstColor) { | ||
| + let color = firstColor | ||
| + if (color.dark()) { | ||
| + color = color.saturate(0.3).rotate(90) | ||
| + } else { | ||
| + color = color.desaturate(0.3).rotate(90) | ||
| + } | ||
| + if (shouldChangeColor(color)) { | ||
| + color = color.rotate(-200).saturate(0.5) | ||
| + } | ||
| + return color | ||
| +} |
| @@ -0,0 +1,43 @@ | ||
| +const crypto = require('crypto') | ||
| +const url = require('url') | ||
| + | ||
| +const sharp = require('sharp') | ||
| +const Color = require('color') | ||
| + | ||
| +const svg = require('./svg') | ||
| +const helper = require('./helper') | ||
| + | ||
| +module.exports = (req, res) => { | ||
| + const {pathname, query} = url.parse(req.url, true) | ||
| + let imageSize = 150 | ||
| + const maxSize = 1000 | ||
| + | ||
| + if (pathname === '/favicon.ico') { | ||
| + return '' | ||
| + } | ||
| + res.setHeader('Cache-Control', 'max-age=2592000, public') | ||
| + if (query.type === 'svg') { | ||
| + res.setHeader('Content-Type', 'svg+xml') | ||
| + } else { | ||
| + res.setHeader('Content-Type', 'image/png') | ||
| + } | ||
| + | ||
| + const hash = crypto.createHash('md5').update(pathname).digest('hex') | ||
| + | ||
| + let firstColor = helper.hashStringToColor(hash) | ||
| + firstColor = new Color(firstColor).saturate(0.5) | ||
| + | ||
| + let avatar = svg.replace('$FIRST', firstColor.hex()) | ||
| + avatar = avatar.replace('$SECOND', helper.getMatchingColor(firstColor).hex()) | ||
| + | ||
| + if (query.type === 'svg') { | ||
| + return avatar | ||
| + } | ||
| + | ||
| + if (query.size && query.size.match(/^-?\d+$/) && query.size <= maxSize) { | ||
| + imageSize = parseInt(query.size, 10) | ||
| + } | ||
| + | ||
| + const png = sharp(new Buffer(avatar)).resize(imageSize, imageSize).png() | ||
| + return png | ||
| +} |
29
package.json
| @@ -0,0 +1,29 @@ | ||
| +{ | ||
| + "name": "avatar", | ||
| + "version": "1.0.0", | ||
| + "main": "index.js", | ||
| + "repository": "tobiaslins/avatar", | ||
| + "scripts": { | ||
| + "start": "micro" | ||
| + }, | ||
| + "author": "Tobias Lins <tobias@lins.in>", | ||
| + "license": "MIT", | ||
| + "dependencies": { | ||
| + "color": "^1.0.3", | ||
| + "micro": "^7.0.3", | ||
| + "sharp": "^0.17.1", | ||
| + "url": "^0.11.0" | ||
| + }, | ||
| + "devDependencies": { | ||
| + "eslint-config-xo-react": "^0.10.0", | ||
| + "xo": "^0.17.1" | ||
| + }, | ||
| + "xo": { | ||
| + "esnext": true, | ||
| + "semicolon": false, | ||
| + "space": true, | ||
| + "env": [ | ||
| + "node" | ||
| + ] | ||
| + } | ||
| +} |
| @@ -0,0 +1,15 @@ | ||
| +module.exports = `<?xml version="1.0" standalone="no"?> | ||
| +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||
| +<svg width="120" height="120" viewBox="120 120 120 120" version="1.1" xmlns="http://www.w3.org/2000/svg"> | ||
| + <g> | ||
| + <defs> | ||
| + <linearGradient id="avatar" x1="0" y1="0" x2="1" y2="1"> | ||
| + <stop offset="0%" stop-color="$FIRST"/> | ||
| + <stop offset="100%" stop-color="$SECOND"/> | ||
| + </linearGradient> | ||
| + </defs> | ||
| + | ||
| + <rect fill="url(#avatar)" x="120" y="120" width="120" height="120"/> | ||
| + </g> | ||
| +</svg> | ||
| +` |
Oops, something went wrong.
0 comments on commit
a55ac84