Skip to content

Commit

Permalink
Build changes from eba394e
Browse files Browse the repository at this point in the history
  • Loading branch information
CircleCI committed Oct 26, 2022
0 parents commit 41663ae
Show file tree
Hide file tree
Showing 32 changed files with 1,923 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-env"]
}
31 changes: 31 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: 2
jobs:
build:
docker:
- image: circleci/php:7.3-node

branches:
only:
# Whitelist branches to build for.
- master
steps:
# Checkout repo & subs:
- checkout

# Get npm cache:
- restore_cache:
key: npm

# Build steps:
- run: npm install
- run: npm run build

# Make fast:
- save_cache:
key: npm
paths:
- ~/.npm

# Run the deploy:
- deploy:
command: .circleci/deploy.sh
13 changes: 13 additions & 0 deletions .circleci/deploy-exclude.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Add files or patterns to exclude from the built branch here.
# Consult the "INCLUDE/EXCLUDE PATTERN RULES" section of the rsync manual for
# supported patterns.
#
# Note: Excluding ".circleci" will cause your branch to fail. Use the
# `branches` option in config.yml instead.

.git
.gitignore
Gruntfile.js
node_modules
package.json
package-lock.json
95 changes: 95 additions & 0 deletions .circleci/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/bin/bash -e
#
# Deploy your branch.
#

DEPLOY_SUFFIX="${DEPLOY_SUFFIX:--built}"
GIT_USER="${DEPLOY_GIT_USER:-CircleCI}"
GIT_EMAIL="${DEPLOY_GIT_EMAIL:-rob+platform-ui-build@hmn.md}"

BRANCH="${CIRCLE_BRANCH}"
SRC_DIR="$PWD"
BUILD_DIR="/tmp/hm-build"

if [[ -z "$BRANCH" ]]; then
echo "No branch specified!"
exit 1
fi

if [[ -d "$BUILD_DIR" ]]; then
echo "WARNING: ${BUILD_DIR} already exists. You may have accidentally cached this"
echo "directory. This will cause issues with deploying."
exit 1
fi

COMMIT=$(git rev-parse HEAD)
VERSION=$(grep 'Version: ' gaussholder.php | grep -oEi '[0-9\.a-z\+-]+$')

if [[ $VERSION != "null" ]]; then
DEPLOY_BRANCH="${VERSION}--branch"
DEPLOY_AS_RELEASE="${DEPLOY_AS_RELEASE:-yes}"
else
DEPLOY_BRANCH="${BRANCH}${DEPLOY_SUFFIX}"
DEPLOY_AS_RELEASE="${DEPLOY_AS_RELEASE:-no}"
fi

echo "Deploying $BRANCH to $DEPLOY_BRANCH"

# If the deploy branch doesn't already exist, create it from the empty root.
if ! git rev-parse --verify "remotes/origin/$DEPLOY_BRANCH" >/dev/null 2>&1; then
echo -e "\nCreating $DEPLOY_BRANCH..."
git worktree add --detach "$BUILD_DIR"
cd "$BUILD_DIR"
git checkout --orphan "$DEPLOY_BRANCH"
else
echo "Using existing $DEPLOY_BRANCH"
git worktree add --detach "$BUILD_DIR" "remotes/origin/$DEPLOY_BRANCH"
cd "$BUILD_DIR"
git checkout "$DEPLOY_BRANCH"
fi

# Ensure we're in the right dir
cd "$BUILD_DIR"

# Remove existing files
git rm -rfq .

# Sync built files
echo -e "\nSyncing files..."
if ! command -v 'rsync'; then
sudo apt-get update
sudo apt-get install -q -y rsync
fi

rsync -av "$SRC_DIR/" "$BUILD_DIR" --exclude-from "$SRC_DIR/.circleci/deploy-exclude.txt"

# Add changed files
git add .

if [ -z "$(git status --porcelain)" ]; then
echo "No changes to built files."
exit
fi

# Print status!
echo -e "\nSynced files. Changed:"
git status -s

# Double-check our user/email config
if ! git config user.email; then
git config user.name "$GIT_USER"
git config user.email "$GIT_EMAIL"
fi

# Commit it.
MESSAGE=$( printf 'Build changes from %s\n\n%s' "${COMMIT}" "${CIRCLE_BUILD_URL}" )
git commit -m "$MESSAGE"

# Push it (real good).
git push origin "$DEPLOY_BRANCH"

# Make a release if one doesn't exist.
if [[ $DEPLOY_AS_RELEASE = "yes" && $(git tag -l "$VERSION") != $VERSION ]]; then
git tag "$VERSION"
git push origin "$VERSION"
fi
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
assets/src/stackblur.js
dist
3 changes: 3 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "@humanmade"
}
20 changes: 20 additions & 0 deletions .webpack/webpack.config.common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
entry: [ './assets/index.js' ],
output: {
filename: 'gaussholder.min.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
loader: 'babel-loader',
},
],
},
plugins: [
new CleanWebpackPlugin(),
],
};
21 changes: 21 additions & 0 deletions .webpack/webpack.config.dev.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const common = require( './webpack.config.common' );

module.exports = {
...common,
mode: 'development',
devtool: 'inline-source-map',
module: {
...common.module,
rules: [
...common.module.rules,
{
test: /\.js?$/,
exclude: /(node_modules|bower_components)/,
enforce: 'pre',
loader: require.resolve( 'eslint-loader' ),
options: {},
},
]

}
};
6 changes: 6 additions & 0 deletions .webpack/webpack.config.prod.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const common = require( './webpack.config.common' );

module.exports = {
...common,
mode: 'production',
};
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Changelog

- Bug: Fix stray characters in img tag attributes #47
25 changes: 25 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Contributing

To get started follow these steps:

1. `git clone [email protected]:humanmade/gaussholder.git` or fork the repository and clone your fork.
1. `cd gaussholder`
1. `npm install`
1. `npm run build` (to build the assets)

You should then start working on your fork or branch.

## Making a pull request

When you make a pull request it will be reviewed. You should also update the `CHANGELOG.md` - add lines after the title such as `- Bug: Fixed a typo #33` to describe each change and link to the issues if applicable.

## Making a new release

1. Create a new branch
2. Update the version number in the comment header of `plugin.php` to reflect the nature of the changes, this plugin follows semver versioning.
- For small changes like bug fixes update the patch version
- For changes that add functionality without changing existing functionality update the minor version
- For breaking or highly significant changes update the major version
3. Add a title heading for the version number above the latest updates in `CHANGELOG.md`
4. Create a pull request for the branch
5. Once merged a release will be built and deployed by CircleCI corresponding to the version number in `plugin.php`
55 changes: 55 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# License

## StackBlur

Gaussholder uses [StackBlur for Canvas][stackblur] by Mario Klingemann; modified
by [Fabien Loison][stackblur-gh]. Licensed under the MIT License.

[stackblur]: http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
[stackblur-gh]: https://github.com/flozz/StackBlur

> Copyright (c) 2010 Mario Klingemann
>
> Permission is hereby granted, free of charge, to any person
> obtaining a copy of this software and associated documentation
> files (the "Software"), to deal in the Software without
> restriction, including without limitation the rights to use,
> copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the
> Software is furnished to do so, subject to the following
> conditions:
>
> The above copyright notice and this permission notice shall be
> included in all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> OTHER DEALINGS IN THE SOFTWARE.
## Gaussholder

Gaussholder is a plugin for (and hence, derivative work of) WordPress. Licensed
under the GNU General Public License version 2 or later.

> WordPress - Web publishing software
>
> Copyright (C) 2003-2010 by the contributors
>
> This program is free software; you can redistribute it and/or modify
> it under the terms of the GNU General Public License as published by
> the Free Software Foundation; either version 2 of the License, or
> (at your option) any later version.
>
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU General Public License for more details.
>
> You should have received a copy of the GNU General Public License along
> with this program; if not, write to the Free Software Foundation, Inc.,
> 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
99 changes: 99 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<table width="100%">
<tr>
<td align="left" width="70">
<strong>Gaussholder</strong><br />
Fast and lightweight image previews, using Gaussian blur.
</td>
<td align="right" width="20%">
<!--
<a href="https://travis-ci.org/humanmade/Gaussholder">
<img src="https://travis-ci.org/humanmade/Gaussholder.svg?branch=master" alt="Build status">
</a>
<a href="http://codecov.io/github/humanmade/Gaussholder?branch=master">
<img src="http://codecov.io/github/humanmade/Gaussholder/coverage.svg?branch=master" alt="Coverage via codecov.io" />
</a>
-->
</td>
</tr>
<tr>
<td>
A <strong><a href="https://hmn.md/">Human Made</a></strong> project. Maintained by @rmccue.
</td>
<td align="center">
<img src="https://hmn.md/content/themes/hmnmd/assets/images/hm-logo.svg" width="100" />
</td>
</tr>
</table>

Gaussholder is an image placeholder utility, generating accurate preview images using an amazingly small amount of data.

<img src="preview.gif" />

That's a **800 byte** preview image, for a **109 kilobyte** image. 800 bytes still too big? Tune the size to your liking in your configuration.

**Please note:** This is still in development, and we're working on getting this production-ready, so things might not be settled yet. In particular, we're still working on tweaking the placeholder size and improving the lazyloading code. Avoid using this in production.

## How does it work?

Gaussholder is inspired by [Facebook Engineering's fantastic post][fbeng] on generating tiny preview images. Gaussholder takes the concepts from this post and applies them to the wild world of WordPress.

In a nutshell, Gaussholder takes a Gaussian blur and applies it to an image to generate a preview image. Gaussian blurs work as a low-pass filter, allowing us to throw away a lot of the data. We then further reduce the amount of data per image by removing the JPEG header and rebuilding it on the client side (this eliminates ~800 bytes from each image).

We further reduce the amount of data for some requests by lazyloading images.

[fbeng]: https://code.facebook.com/posts/991252547593574

## How do I use it?

Gaussholder is designed for high-volume sites for seriously advanced users. Do _not_ install this on your regular WP site.

1. Download and activate the plugin from this repo.
2. Select the image sizes to use Gaussholder on, and add them to the array on the `gaussholder.image_sizes` filter.
3. If you have existing images, regenerate the image thumbnails.

Your filter should look something like this:

```php
add_filter( 'gaussholder.image_sizes', function ( $sizes ) {
$sizes['medium'] = 16;
$sizes['large'] = 32;
$sizes['full'] = 84;
return $sizes;
} );
```

The keys are registered image sizes (plus `full` for the original size), with the value as the desired blur radius in pixels.

By default, Gaussholder won't generate any placeholders, and you need to opt-in to using it. Simply filter here, and add the size names for what you want generated.

Be aware that for every size you add, a placeholder will be generated and stored in the database. If you have a lot of sizes, this will be a _lot_ of data.

By default Gaussholder is initialized with the `DOMContentLoaded` event. Should you need to reinitialize Gaussholder after the page had loaded, this can be achieved with `GaussHolder();`.

### Blur radius

The blur radius controls how much blur we use. The image is pre-scaled down by this factor, and this is really the key to how the placeholders work. Increasing radius decreases the required data quadratically: a radius of 2 uses a quarter as much data as the full image; a radius of 8 uses 1/64 the amount of data. (Due to compression, the final result will *not* follow this scaling.)

Be careful tuning this, as decreasing the radius too much will cause a huge amount of data in the body; increasing it will end up with not enough data to be an effective placeholder.

The radius needs to be tuned to each size individually. Facebook uses about 200 bytes of data for their placeholders, but you may want higher quality placeholders. There's no ideal radius, as you simply want to balance having a useful placeholder with the extra time needed to process the data on the page.

Gaussholder includes a CLI command to help you tune the radius: pick a representative attachment or image file and use `wp gaussholder check-size <id_or_image> <radius>`. Adjust the radius until you get to roughly 200B, then check against other attachments to ensure they're in the ballpark.

Note: changing the radius requires regenerating the placeholder data. Run `wp gaussholder process-all --regenerate` after changing radii or adding new sizes.

## License
Gaussholder is licensed under the GPLv2 or later.

Gaussholder uses StackBlur, licensed under the MIT license.

See [LICENSE.md](LICENSE.md) for further details.

## Credits
Created by Human Made for high volume and large-scale sites.

Written and maintained by [Ryan McCue](https://github.com/rmccue). Thanks to all our [contributors](https://github.com/humanmade/Gaussholder/graphs/contributors). (Thanks also to fellow humans Matt and Paul for the initial placeholder code.)

Gaussholder is heavily inspired by [Facebook Engineering's post][fbeng], and would not have been possible without it. In particular, the techniques of downscaling before blurring and extracting the JPEG header are particularly novel, and the key to why Gaussholder exists.

Interested in joining in on the fun? [Join us, and become human!](https://hmn.md/is/hiring/)
Binary file added assets/blank.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions assets/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Gaussholder from './src/gaussholder';

document.addEventListener( 'DOMContentLoaded', Gaussholder );

// Add the Gaussholder function to the window object.
window.GaussHolder = Gaussholder;
Loading

0 comments on commit 41663ae

Please sign in to comment.