-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathcli.js
More file actions
executable file
·66 lines (60 loc) · 2.44 KB
/
cli.js
File metadata and controls
executable file
·66 lines (60 loc) · 2.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!/usr/bin/env node
const fetch = require('node-fetch');
const emojis = require('node-emoji');
const getTweets = require('./parser').getTweets;
const JSDOM = require('jsdom').JSDOM;
const { rewriteUrl, downloadResources } = require('./resourceManager');
const [,, threadReaderUrl, rsrcDirPath, rsrcUrlPath] = process.argv;
function processDocument(document, { extractResources = false, resourcesUrlPath = '.' }) {
const resources = [];
const urlTransformer = extractResources ? rewriteUrl(resourcesUrlPath) : x => x;
const html = getTweets(document)
.map(({ tweetHTML, images, videos }) => {
const imagesHTML = images.map(img => {
if (extractResources) {
resources.push(img.url);
}
return imageToHtml(urlTransformer)(img);
});
const videosHTML = videos.map(video => {
if (extractResources) {
resources.push(video.poster);
video.sources.forEach(source => resources.push(source.src));
}
return videoToHtml(urlTransformer)(video);
});
return { tweetHTML: emojis.strip(tweetHTML), imagesHTML, videosHTML };
})
.map(({ tweetHTML, imagesHTML, videosHTML }) => {
const tags = [ `<p>${tweetHTML}</p>` ];
if (imagesHTML.length > 0) { tags.push(`<figure style="display:flex">${imagesHTML.join('')}</figure>`); }
if (videosHTML.length > 0) { tags.push(`<figure>${videosHTML.join('')}</figure>`); }
return tags;
})
.reduce((acc, tweetParts) => acc.concat(tweetParts), []) // alternative for missing .flat
.join('');
return { html, resources };
}
const imageToHtml = urlTransformer => ({ url }) =>
`<a class="media-link" href="${urlTransformer(url)}">
<img class="media" loading="lazy" src="${urlTransformer(url)}" alt="" />
</a>`;
const videoToHtml = urlTransformer => ({ poster, sources }) => {
const types = sources.map(({ src, type }) => `<source src="${urlTransformer(src)}" type="${type}" />`);
return `<video controls="" poster="${urlTransformer(poster)}">
${types.join('')}
<img alt="" src="${urlTransformer(poster)}" />
</video>`;
}
fetch(threadReaderUrl)
.then(response => response.text())
.then(html => new JSDOM(html).window.document)
.then(doc => processDocument(doc, {
extractResources: !!rsrcDirPath,
resourcesUrlPath: rsrcUrlPath || rsrcDirPath
}))
.then(async ({ html, resources }) => {
await downloadResources(resources, rsrcDirPath);
return html;
})
.then(console.log);