Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions lib/collections.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import chunk from './helpers/chunk.js';
import {slugify, padStart, specialTagMeta, specialTagValue} from './filters.js';
import {slugify, specialTagMeta, specialTagValue, whereKeyEquals} from './filters.js';
import listData from '../src/_data/lists-meta.js';
import metadata from "../src/_data/metadata.js";

Expand Down Expand Up @@ -216,14 +216,22 @@ const collectSpecialTaggedContent = ({prefix, collection, glob = './src/content/
*/
const lists = (collection) => collection.getFilteredByTag('type/list').map(item => {
const slug = item.data?.list_slug ?? item.fileSlug;
let items;

// If sidebar_component is `books` then origin is `bookwyrm` data source and not the `list` special tag.
if (item?.data?.sidebar_component === 'books' && item?.data?.sidebar_shelves) {
items = item?.data?.bookwyrm ? whereKeyEquals(item.data.bookwyrm, 'shelf', item.data.sidebar_shelves) : [];
} else {
items = collection.getFilteredByTag(`list/${slug}`).reverse();
}

return {
title: item.data.title,
description: item.data?.description,
url: item.url,
slug,
list_category: item.data.list_category,
items: collection.getFilteredByTag(`list/${slug}`).reverse(),
items,
}
});

Expand Down
122 changes: 72 additions & 50 deletions lib/helpers/screenshot.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ const variableHash = (data, size = 5, encoding = 'hex') => {
return output.toString(encoding);
}

/**
* List of requests to process after Eleventy has built the site
* @type {Array<{url: string, filePathName: string, src: string}>}
*/
const requestQueue = [];

/**
* @param { import('@11ty/eleventy/src/UserConfig') } eleventyConfig
* @param { * } customOptions
Expand All @@ -34,7 +40,8 @@ export default function (eleventyConfig, {dpr = 1, viewport = [1200, 630], timeo
// Must be between 3000 and 8500
timeout = Math.min(Math.max(timeout, 3000), 8500);

eleventyConfig.addAsyncShortcode('screenshot', async (url, filename) => {
eleventyConfig.addShortcode('screenshot', (url, filename) => {
// Hash the URL to create a unique filename
const hash = variableHash(url, 12);

// Path to where the screenshot will be saved
Expand All @@ -46,57 +53,72 @@ export default function (eleventyConfig, {dpr = 1, viewport = [1200, 630], timeo
// If we have already created a screenshot for this URL, return the src value
if (fs.existsSync(filePathName)) return src;

const browser = await puppeteer.launch({
executablePath: await chromium.executablePath(),
args: chromium.args,
defaultViewport: {
width: viewport[0],
height: viewport[1],
deviceScaleFactor: parseFloat(dpr),
},
headless: chromium.headless,
});

const page = await browser.newPage();

/*
const customUA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36';
await page.setUserAgent(customUA);
*/

// Borrowed from https://github.com/11ty/api-screenshot/blob/v1/functions/screenshot.js
let response = await Promise.race([
page.goto(url, {
waitUntil: ["load"], // TODO: maybe add networkidle0, domcontentloaded, etc as options?
timeout,
}),
new Promise(resolve => {
setTimeout(() => {
resolve(false); // false is expected below
}, timeout - 1500); // we need time to execute the window.stop before the top level timeout hits
}),
]);

if (response === false) { // timed out, resolved false
await page.evaluate(() => window.stop());
}

await page.screenshot({
path: filePathName,
type: 'jpeg',
quality: 80,
fullPage: false,
captureBeyondViewport: false,
clip: {
x: 0,
y: 0,
width: viewport[0],
height: viewport[1],
}
// Else enqueue the request and return the src value. This allows 11ty to build the site first and
// we shall process the queue in the `eleventy.after` lifecycle hook.
requestQueue.push({
url,
filePathName,
src,
});

await browser.close();

return src;
});

eleventyConfig.on('eleventy.after', async () => {
console.log(`[@photogabble/screenshot] Processing ${requestQueue.length} requests`);

return Promise.all(requestQueue.map(async ({url, filePathName}) => {
const browser = await puppeteer.launch({
executablePath: await chromium.executablePath(),
args: chromium.args,
defaultViewport: {
width: viewport[0],
height: viewport[1],
deviceScaleFactor: parseFloat(dpr),
},
headless: chromium.headless,
});

const page = await browser.newPage();

/*
const customUA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36';
await page.setUserAgent(customUA);
*/

// Borrowed from https://github.com/11ty/api-screenshot/blob/v1/functions/screenshot.js
let response = await Promise.race([
page.goto(url, {
waitUntil: ["load"], // TODO: maybe add networkidle0, domcontentloaded, etc as options?
timeout,
}),
new Promise(resolve => {
setTimeout(() => {
resolve(false); // false is expected below
}, timeout - 1500); // we need time to execute the window.stop before the top level timeout hits
}),
]);

if (response === false) { // timed out, resolved false
await page.evaluate(() => window.stop());
}

await page.screenshot({
path: filePathName,
type: 'jpeg',
quality: 80,
fullPage: false,
captureBeyondViewport: false,
clip: {
x: 0,
y: 0,
width: viewport[0],
height: viewport[1],
}
});

await browser.close();
}));

})
}
2 changes: 1 addition & 1 deletion lib/shortcodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export const buttonBoard = (items) => {
html += `<a href="${href}" class="no-ext btn-88x31" rel="noopener" title="Visit ${title}"><img width="88" height="31" src="${button}" alt="88x31 button for ${title}" aria-hidden="true"/></a>`;
}

return `<nav class="button-board">${html}</nav>`;
return `<nav class="button-board full-width">${html}</nav>`;
}

/**
Expand Down
Loading