Skip to content

Commit

Permalink
feat(projects): Adds project thumbs and descriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
lupomontero committed Oct 27, 2021
1 parent e3f5d9f commit b3f968a
Show file tree
Hide file tree
Showing 11 changed files with 3,837 additions and 1,761 deletions.
91 changes: 90 additions & 1 deletion lib/project.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
const { Buffer } = require('buffer');
const path = require('path');
const fs = require('fs');
const https = require('https');
const marked = require('marked');
const yaml = require('js-yaml');
const { JSDOM } = require('jsdom');
const sharp = require('sharp');
const { getReadmeFileName } = require('./common');
const pkg = require('../package.json');


const { readFile } = fs.promises;
const { stat, readFile, writeFile } = fs.promises;


const getProjectTitle = ([token]) => {
Expand Down Expand Up @@ -130,6 +134,89 @@ const getLearningObjectives = async (dir, opts) => {
};


const getSummary = (tokens) => {
const headingIdx = tokens.findIndex(token => (
token.type === 'heading'
&& token.depth === 2
&& /(resumen|resumo)/i.test(token.text)
));

if (headingIdx === -1 || tokens[headingIdx + 1].type !== 'paragraph') {
return null;
}

return marked.parse(tokens[headingIdx + 1].text);
};


const fetchImage = src => new Promise((resolve, reject) => {
https.get(src, (resp) => {
if (resp.statusCode !== 200) {
return reject(new Error(`HTTP error ${resp.statusCode}`));
}

let buffer;
resp.on('error', reject);
resp.on('data', (chunk) => {
buffer = (typeof buffer === 'undefined')
? chunk
: Buffer.concat([buffer, chunk]);
});
return resp.on('end', () => resolve(buffer));
});
});


const getCoverImage = (tokens) => {
const firstTokenWithImg = tokens.find(token => (
token.type === 'paragraph'
&& (
/!\[.+\]\(.+\)/g.test(token.text)
|| /<img /g.test(token.text)
)
));

if (!firstTokenWithImg) {
return null;
}

const html = marked.parse(firstTokenWithImg.text);
const { window } = new JSDOM(html);
return window.document.querySelector('img').src;
};


const getImages = (dir, tokens) => {
const cover = getCoverImage(tokens);
const thumbFile = path.join(dir, 'thumb.png');

const createThumb = async (src) => {
const buffer = await fetchImage(src);
const data = await sharp(buffer).resize(395).toBuffer();
await writeFile(thumbFile, data, { encoding: 'base64' });
return data;
};

return stat(thumbFile)
.then(() => readFile(thumbFile, 'base64'))
.catch((err) => {
if (err.code !== 'ENOENT') {
throw err;
}
// does not exist!
return !cover ? null : createThumb(cover);
})
.then(data => ({
cover,
thumb: (
data
? `data:image/png;base64,${data.toString('base64')}`
: null
),
}));
};


module.exports = (dir, { Project }, opts = {}) => {
const readme = path.join(dir, getReadmeFileName(opts.locale));
const basename = path.basename(dir);
Expand Down Expand Up @@ -170,7 +257,9 @@ module.exports = (dir, { Project }, opts = {}) => {
title: getProjectTitle(tokens),
locale: opts.locale,
track: opts.track,
summary: getSummary(tokens),
learningObjectives: await getLearningObjectives(dir, opts),
...(await getImages(dir, tokens)),
}))
.then((json) => {
const project = new Project(json);
Expand Down
Loading

0 comments on commit b3f968a

Please sign in to comment.