Skip to content

Commit

Permalink
fetch sponsors at build time, show ALL non-skeevy sponsors; closes #4271
Browse files Browse the repository at this point in the history
 (#4272)

* Show all sponsors on site

- change ordering: sponsors, then backers
- blacklist bad actors
- rename `default.html` to `default.liquid`, because it's a Liquid template.
- fiddles with the CSS a bit
- do not attempt to display a link if there is no website

* use smaller imgs for backers

* Fetch all open collective sponsor images to save their dimensions

* Reworked avatars. LEss reflows due to image dimensions. Smoother loading animation that doesn't wait for all images. Progressive enhanced

* Add standardised lazy loading to all images

* Set height on badges to avoid page reflows

* Add node version specification in .nvmrc to get netlify up to date

* Move avatars javascript to external file for better development experience

Co-authored-by: Peter Müller <[email protected]>
  • Loading branch information
2 people authored and craigtaub committed May 22, 2020
1 parent 19f1841 commit c967789
Show file tree
Hide file tree
Showing 13 changed files with 1,302 additions and 1,152 deletions.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
12
21 changes: 21 additions & 0 deletions docs/_data/blacklist.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[
"cheap-writing-service",
"emailmarketingservices-io",
"device-tricks1",
"my-true-media",
"yiannakis-ttafounas-ttafounas",
"writerseperhour",
"casinotop-com",
"casino-topp",
"casinoutanreg",
"supercazino-ro",
"igor-noskov",
"blue-link-seo",
"casino-online",
"domywriting",
"writemypaper4me",
"trust-my-paper",
"seowebsitetraffic-net",
"pfannen-test",
"mochajs"
]
133 changes: 133 additions & 0 deletions docs/_data/supporters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/usr/bin/env node
'use strict';

const debug = require('debug')('mocha:docs:data:supporters');
const needle = require('needle');
const imageSize = require('image-size');
const blacklist = new Set(require('./blacklist.json'));

const API_ENDPOINT = 'https://api.opencollective.com/graphql/v2';

const query = `query account($limit: Int, $offset: Int, $slug: String) {
account(slug: $slug) {
orders(limit: $limit, offset: $offset) {
limit
offset
totalCount
nodes {
fromAccount {
name
slug
website
imgUrlMed: imageUrl(height:64)
imgUrlSmall: imageUrl(height:32)
type
}
totalDonations {
value
}
createdAt
}
}
}
}`;

const graphqlPageSize = 1000;

const nodeToSupporter = node => ({
name: node.fromAccount.name,
slug: node.fromAccount.slug,
website: node.fromAccount.website,
imgUrlMed: node.fromAccount.imgUrlMed,
imgUrlSmall: node.fromAccount.imgUrlSmall,
firstDonation: node.createdAt,
totalDonations: node.totalDonations.value * 100,
type: node.fromAccount.type
});

/**
* Retrieves donation data from OC
*
* Handles pagination
* @param {string} slug - Collective slug to get donation data from
* @returns {Promise<Object[]>} Array of raw donation data
*/
const getAllOrders = async (slug = 'mochajs') => {
let allOrders = [];
const variables = {limit: graphqlPageSize, offset: 0, slug};

// Handling pagination if necessary (2 pages for ~1400 results in May 2019)
while (true) {
const result = await needle(
'post',
API_ENDPOINT,
{query, variables},
{json: true}
);
const orders = result.body.data.account.orders.nodes;
allOrders = [...allOrders, ...orders];
variables.offset += graphqlPageSize;
if (orders.length < graphqlPageSize) {
debug('retrieved %d orders', allOrders.length);
return allOrders;
} else {
debug(
'loading page %d of orders...',
Math.floor(variables.offset / graphqlPageSize)
);
}
}
};

module.exports = async () => {
const orders = await getAllOrders();
// Deduplicating supporters with multiple orders
const uniqueSupporters = new Map();

const supporters = orders
.map(nodeToSupporter)
.filter(supporter => !blacklist.has(supporter.slug))
.reduce((supporters, supporter) => {
if (uniqueSupporters.has(supporter.slug)) {
// aggregate donation totals
uniqueSupporters.get(supporter.slug).totalDonations +=
supporter.totalDonations;
return supporters;
}
uniqueSupporters.set(supporter.slug, supporter);
return [...supporters, supporter];
}, [])
.sort((a, b) => b.totalDonations - a.totalDonations)
.reduce(
(supporters, supporter) => {
if (supporter.type === 'INDIVIDUAL') {
supporters.backers.push({
...supporter,
avatar: supporter.imgUrlSmall
});
} else {
supporters.sponsors.push({...supporter, avatar: supporter.imgUrlMed});
}
return supporters;
},
{sponsors: [], backers: []}
);

// Fetch images for sponsors and save their image dimensions
await Promise.all(
supporters.sponsors.map(async sponsor => {
for await (const chunk of needle.get(sponsor.avatar)) {
sponsor.dimensions = imageSize(chunk);
break;
}
})
);

debug(
'found %d valid backers and %d valid sponsors (%d total)',
supporters.backers.length,
supporters.sponsors.length,
supporters.backers.length + supporters.sponsors.length
);
return supporters;
};
7 changes: 0 additions & 7 deletions docs/_includes/backers.md

This file was deleted.

15 changes: 5 additions & 10 deletions docs/_includes/default.html → docs/_includes/default.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>{{ title }}</title>
<link
rel="preload"
href="https://opencollective.com/static/images/user.svg"
as="image"
crossorigin="anonymous"
/>
<link rel="stylesheet" href="css/normalize.css" />
<link rel="stylesheet" href="css/style.css" />
<link rel="stylesheet" href="css/prism.css" />
Expand All @@ -22,7 +16,7 @@
<header id="_header">
<h1>
<a href="/">
<img id="mocha-logo" src="/images/mocha-logo.svg" alt="Mocha logo" />
<img id="mocha-logo" loading="eager" src="/images/mocha-logo.svg" alt="Mocha logo" />
</a>
</h1>
<p id="tag"><em>simple</em>, <em>flexible</em>, <em>fun</em></p>
Expand All @@ -36,7 +30,7 @@ <h1>
rel="external noopener"
title="Mocha is sponsored by Matomo"
>
<img src="images/matomo-logo.png?trim" alt="Matomo logo" />
<img src="images/matomo-logo.png?trim" loading="lazy" alt="Matomo logo" />
</a>
<a
title="Mocha is an OpenJS Foundation Project"
Expand All @@ -45,6 +39,7 @@ <h1>
>
<img
src="/images/openjsf-logo.svg"
loading="lazy"
width="300"
height="94"
alt="OpenJS Foundation Logo"
Expand All @@ -56,7 +51,7 @@ <h1>
title="Mocha is sponsored by Wallaby"
>
<figure id="wallaby-logo">
<img src="images/wallaby-logo.png?trim" alt="Wallaby logo" />
<img src="images/wallaby-logo.png?trim" loading="lazy" alt="Wallaby logo" />
<figcaption>Wallaby</figcaption>
</figure>
</a>
Expand Down Expand Up @@ -153,7 +148,7 @@ <h1>
<div class="netlify-badge">
<a href="https://www.netlify.com">
<img
src="https://www.netlify.com/img/global/badges/netlify-color-accent.svg"
src="https://www.netlify.com/img/global/badges/netlify-color-accent.svg" loading="lazy"
/>
</a>
</div>
Expand Down
10 changes: 0 additions & 10 deletions docs/_includes/sponsors.md

This file was deleted.

37 changes: 37 additions & 0 deletions docs/_includes/supporters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## Sponsors

Use Mocha at Work? Ask your manager or marketing team if they'd help [support](https://opencollective.com/mochajs#support) our project. Your company's logo will also be displayed on [npmjs.com](http://npmjs.com/package/mocha) and our [GitHub repository](https://github.com/mochajs/mocha#sponsors).

<ul class="image-list" id="sponsors">
{%- for supporter in supporters.sponsors -%}
<li>
{%- if supporter.website -%}
<a href="{{ supporter.website }}" target="_blank" rel="noopener" title="{{ supporter.name }}">
{%- endif -%}
<img src="{{ supporter.avatar }}" width="{{ supporter.dimensions.width }}" height="{{ supporter.dimensions.height }}" alt="{{ supporter.name }}" />
{%- if supporter.website -%}
</a>
{%- endif -%}
</li>
{%- endfor -%}
</ul>

## Backers

Find Mocha helpful? Become a [backer](https://opencollective.com/mochajs#support) and support Mocha with a monthly donation.

<ul class="image-list faded-images" id="backers">
{%- for supporter in supporters.backers -%}
<li>
{%- if supporter.website -%}
<a href="{{ supporter.website }}" target="_blank" rel="noopener" title="{{ supporter.name }}">
{%- endif -%}
<img src="{{ supporter.avatar }}" alt="{{ supporter.name }}" />
{%- if supporter.website -%}
</a>
{%- endif -%}
</li>
{%- endfor -%}
</ul>

<script src="/js/avatars.js"></script>
55 changes: 35 additions & 20 deletions docs/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,42 +74,57 @@ nav.badges a + a {
margin-left: 3px;
}

.image-list {
ul.image-list {
overflow: hidden;
text-align: center;
list-style: none;
column-count: 1;
padding: 0;
margin: 0;
}

.image-list a {
ul.image-list li {
border-bottom: none;
display: inline-block;
margin: 6px;
margin: 0 4px 0 4px;
max-height: 64px;
padding: 0;
line-height: 0;
}

.image-list a img {
ul.image-list li a {
display: inline-block;
}

ul.image-list li img {
margin: 0;
padding: 0;
display: block;
height: 64px;
max-height: 64px;
}

.faded-images {
background-color: #ddd;
border: 1px solid;
border-color: #ddd #ddd #ccc;
border-radius: 3px;
padding: 1em;
box-shadow: inset 0 0 10px #ccc;
ul#backers.image-list li img {
width: 32px;
height: 32px;
overflow: hidden;
}

.faded-images img {
opacity: 0;
transition: opacity 0.3s;
.faded-image {
background-color: rgba(0, 0, 0, 0.05);
}

.faded-images.is-loaded img {
opacity: 1;
.faded-image.is-loaded {
background-color: rgba(0, 0, 0, 0);
transition: background-color 0.3s;
}

#_backers a img {
background: url(/images/backer-background.svg?inline) center center no-repeat;
width: 64px;
.faded-image img {
opacity: 0;
transition: opacity 0.1s;
}

.faded-image.is-loaded img {
opacity: 1;
}

h2 {
Expand Down
12 changes: 0 additions & 12 deletions docs/images/backer-background.svg

This file was deleted.

Loading

0 comments on commit c967789

Please sign in to comment.