From 552ae6d2a66f438fea97541785fd1071514c38d3 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Mon, 19 Oct 2020 21:51:38 +0200 Subject: [PATCH 01/37] Dockerize Paper Hacker News --- Dockerfile | 12 ++++++++++++ scripts/main_loop.sh | 14 ++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 Dockerfile create mode 100755 scripts/main_loop.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..944ca65 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM node:14.12 + +RUN apt-get update +RUN npm install http-server -g +RUN git clone https://github.com/wolfgang42/paper-hn.git + +WORKDIR /paper-hn +RUN yarn install + +COPY /scripts/main_loop.sh . + +CMD /paper-hn/main_loop.sh diff --git a/scripts/main_loop.sh b/scripts/main_loop.sh new file mode 100755 index 0000000..ba86955 --- /dev/null +++ b/scripts/main_loop.sh @@ -0,0 +1,14 @@ +#! /bin/bash + +cd /paper-hn + +http-server . >http.log 2>&1 & +echo Starting up... > index.html + +while true +do + node --experimental-modules ./bin/generate-html.mjs + sleep 60 + rm cache/hn/*.json +done + From 94472bb95096f07077922b5b5db408ce3c2aadeb Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Mon, 19 Oct 2020 21:52:41 +0200 Subject: [PATCH 02/37] Set regenerating interval to 300s --- scripts/main_loop.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main_loop.sh b/scripts/main_loop.sh index ba86955..03610c3 100755 --- a/scripts/main_loop.sh +++ b/scripts/main_loop.sh @@ -8,7 +8,7 @@ echo Starting up... > index.html while true do node --experimental-modules ./bin/generate-html.mjs - sleep 60 + sleep 300 rm cache/hn/*.json done From 847a277d43e11eb85a0a7593f81784ed987c0c20 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Mon, 19 Oct 2020 22:00:51 +0200 Subject: [PATCH 03/37] Use refresh interval variable defaulting to 300 seconds --- scripts/main_loop.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/main_loop.sh b/scripts/main_loop.sh index 03610c3..3cfd4a1 100755 --- a/scripts/main_loop.sh +++ b/scripts/main_loop.sh @@ -1,5 +1,7 @@ #! /bin/bash + +REFRESH_INTERVAL=${REFRESH_INTERVAL:-300} cd /paper-hn http-server . >http.log 2>&1 & @@ -8,7 +10,7 @@ echo Starting up... > index.html while true do node --experimental-modules ./bin/generate-html.mjs - sleep 300 + sleep $REFRESH_INTERVAL rm cache/hn/*.json done From 3712c1f481a910e70d5b0145506a001f6e1bae68 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sun, 25 Oct 2020 10:15:05 +0000 Subject: [PATCH 04/37] Fix TypeError [ERR_INVALID_URL]: Invalid URL: undefined --- bin/generate-html.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/generate-html.mjs b/bin/generate-html.mjs index c6018be..de75e2a 100644 --- a/bin/generate-html.mjs +++ b/bin/generate-html.mjs @@ -34,7 +34,6 @@ import html2text from 'html2plaintext' const jobs = [] for (const jobid of (await hnget('jobstories')).slice(0, 3)) { const job = await getitem(jobid) - job.domain = psl.parse(new URL(job.url).hostname).domain const split = job.title.split(' ') const splitix = (split.findIndex(w => w.toLowerCase() === 'hiring') || 3)+1 job.title1 = split.slice(0, splitix).join(' ') From 44055267bd7c97ea68716ec67db81a9240cd7675 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sun, 25 Oct 2020 10:20:46 +0000 Subject: [PATCH 05/37] Add own repo because of upstream not maintained --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 944ca65..b4fd4db 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM node:14.12 RUN apt-get update RUN npm install http-server -g -RUN git clone https://github.com/wolfgang42/paper-hn.git +RUN git clone https://github.com/mihaigalos/paper-hn WORKDIR /paper-hn RUN yarn install From 0e91d021d7de56ee14cbebeb0e72c3183a0eefb5 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sun, 25 Oct 2020 10:57:10 +0100 Subject: [PATCH 06/37] Abstractify source --- Dockerfile | 2 +- README.md | 2 +- bin/generate-html-hn.mjs | 62 ++++++++++++++++++++++++++++++++++++++++ bin/generate-html.mjs | 54 ---------------------------------- lib/hn.mjs | 14 +++++---- package.json | 4 +-- scripts/main_loop.sh | 2 +- 7 files changed, 75 insertions(+), 65 deletions(-) create mode 100644 bin/generate-html-hn.mjs delete mode 100644 bin/generate-html.mjs diff --git a/Dockerfile b/Dockerfile index b4fd4db..5c8be05 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM node:14.12 RUN apt-get update RUN npm install http-server -g -RUN git clone https://github.com/mihaigalos/paper-hn +COPY . /paper-hn WORKDIR /paper-hn RUN yarn install diff --git a/README.md b/README.md index f24860d..74611e2 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Hacker News front page in the style of a print newspaper. ## How to run ``` yarn install -node ./bin/generate-html.mjs +node ./bin/generate-html-hn.mjs ``` This will create an `index.html` file which you can view. diff --git a/bin/generate-html-hn.mjs b/bin/generate-html-hn.mjs new file mode 100644 index 0000000..212482b --- /dev/null +++ b/bin/generate-html-hn.mjs @@ -0,0 +1,62 @@ +import{hnget, getitem} from '../lib/hn.mjs' import{ + init_titles, title_keyword} from '../lib/keywords.mjs' import{ + page_info} from '../lib/page-extract.mjs' import pug from 'pug' import fs + from 'fs-extra' import psl from 'psl' import html2text from 'html2plaintext' + + ; +(async() = + > + { + await fs.ensureDir('cache/hn/item') await fs.ensureDir('cache/url') + + await + init_titles() + + const stories = [] const source = + 'https://hacker-news.firebaseio.com/v0/' for (const storyid of( + await hnget( + source, + 'topstories')) + .slice(0, 30)) { + const story = + await getitem(source, + storyid) if (story.type != + = 'story') continue // Filter out jobs + story.keyword = + title_keyword(story.title) if (story.text) { // Self post + story.url = + 'https://news.ycombinator.com/item?id=' + story.id story.domain = + 'news.ycombinator.com' story.paragraph = + html2text(story.text.split('

')[0]) story.image = false + } + else {story.domain = + psl.parse(new URL(story.url).hostname).domain const info = + await page_info(story.url) story.paragraph = + info.paragraph story.image = + info.image} stories.push(story) + } + + const jobstories = await hnget(source_url, 'jobstories', + cache_path) if (jobstories != null) { + for (const jobid of jobstories.slice(0, 3)) { + const job = await getitem(source_url, jobid, cache_path) + const split = job.title.split(' ') const splitix = + (split.findIndex(w = > w.toLowerCase() == = 'hiring') || 3) + + 1 job.title1 = split.slice(0, splitix).join(' ') job.title2 = + split.slice(splitix).join(' ') jobs.push(job) + } + } + + await fs.writeFile('index.html', pug.renderFile('index.pug', { + stories, + jobs, + date : new Date(1000 * Math.max(... stories.map(s = > s.time))) + .toLocaleString('en-US', { + timeZone : 'UTC', + dateStyle : 'full', + timeStyle : 'short', + timeZoneName : 'short', + }), + })) + })() + .then(null, err = > {throw err}) diff --git a/bin/generate-html.mjs b/bin/generate-html.mjs deleted file mode 100644 index de75e2a..0000000 --- a/bin/generate-html.mjs +++ /dev/null @@ -1,54 +0,0 @@ -import {hnget, getitem} from '../lib/hn.mjs' -import {init_titles, title_keyword} from '../lib/keywords.mjs' -import {page_info} from '../lib/page-extract.mjs' -import pug from 'pug' -import fs from 'fs-extra' -import psl from 'psl' -import html2text from 'html2plaintext' - -;(async () => { - await fs.ensureDir('cache/hn/item') - await fs.ensureDir('cache/url') - - await init_titles() - - const stories = [] - for (const storyid of (await hnget('topstories')).slice(0, 30)) { - const story = await getitem(storyid) - if (story.type !== 'story') continue // Filter out jobs - story.keyword = title_keyword(story.title) - if (story.text) { // Self post - story.url = 'https://news.ycombinator.com/item?id='+story.id - story.domain = 'news.ycombinator.com' - story.paragraph = html2text(story.text.split('

')[0]) - story.image = false - } else { - story.domain = psl.parse(new URL(story.url).hostname).domain - const info = await page_info(story.url) - story.paragraph = info.paragraph - story.image = info.image - } - stories.push(story) - } - - const jobs = [] - for (const jobid of (await hnget('jobstories')).slice(0, 3)) { - const job = await getitem(jobid) - const split = job.title.split(' ') - const splitix = (split.findIndex(w => w.toLowerCase() === 'hiring') || 3)+1 - job.title1 = split.slice(0, splitix).join(' ') - job.title2 = split.slice(splitix).join(' ') - jobs.push(job) - } - - await fs.writeFile('index.html', pug.renderFile('index.pug', { - stories, - jobs, - date: new Date(1000*Math.max(...stories.map(s => s.time))).toLocaleString('en-US', { - timeZone: 'UTC', - dateStyle: 'full', - timeStyle: 'short', - timeZoneName: 'short', - }), - })) -})().then(null, err => {throw err}) diff --git a/lib/hn.mjs b/lib/hn.mjs index 12a26c1..17ee1c7 100644 --- a/lib/hn.mjs +++ b/lib/hn.mjs @@ -1,20 +1,22 @@ import fetch from 'node-fetch' import fs from 'fs-extra' -export async function hnget(q) { +export async function hnget(source, q) { const cache = `cache/hn/${q}.json` if (await fs.exists(cache)) { return fs.readJson(cache) } - const res = await fetch(`https://hacker-news.firebaseio.com/v0/${q}.json`) - if (!res.ok) { - throw new Error(`HTTP error: ${res.status} for ${q}`) + const url = `${source}${q}.json` + const res = await fetch(url) + if (!res.ok) + { + throw new Error(`HTTP error: ${res.status} for ${source}${q}.json`) } const ret = await res.json() await fs.writeJson(cache, ret) return ret } -export async function getitem(itemid) { - return await hnget(`item/${itemid}`) +export async function getitem(source,itemid) { + return await hnget(source,`item/${itemid}`) } diff --git a/package.json b/package.json index 36ba950..94cc6f9 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,6 @@ "url-toolkit": "^2.2.0" }, "scripts": { - "watch": "nodemon -e mjs,pug ./bin/generate-html.mjs" + "watch": "nodemon -e mjs,pug ./bin/generate-html-hn.mjs" } -} +} \ No newline at end of file diff --git a/scripts/main_loop.sh b/scripts/main_loop.sh index 3cfd4a1..ca36011 100755 --- a/scripts/main_loop.sh +++ b/scripts/main_loop.sh @@ -9,7 +9,7 @@ echo Starting up... > index.html while true do - node --experimental-modules ./bin/generate-html.mjs + node --trace-warnings --experimental-modules ./bin/generate-html-hn.mjs sleep $REFRESH_INTERVAL rm cache/hn/*.json done From 2c36c9c701f787cf34f516a0cc96f1594a0b9b56 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sun, 25 Oct 2020 12:08:07 +0100 Subject: [PATCH 07/37] Add lobste.rs as source, separate docker file --- Dockerfile | 4 +- DockerfileLobster | 12 +++++ bin/generate-html-laarc.mjs | 56 +++++++++++++++++++++++ scripts/{main_loop.sh => main_loop_hn.sh} | 0 scripts/main_loop_lobster.sh | 16 +++++++ 5 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 DockerfileLobster create mode 100644 bin/generate-html-laarc.mjs rename scripts/{main_loop.sh => main_loop_hn.sh} (100%) create mode 100755 scripts/main_loop_lobster.sh diff --git a/Dockerfile b/Dockerfile index 5c8be05..32f4c2e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,6 @@ COPY . /paper-hn WORKDIR /paper-hn RUN yarn install -COPY /scripts/main_loop.sh . +COPY /scripts/main_loop_hn.sh . -CMD /paper-hn/main_loop.sh +CMD /paper-hn/main_loop_hn.sh diff --git a/DockerfileLobster b/DockerfileLobster new file mode 100644 index 0000000..9d26552 --- /dev/null +++ b/DockerfileLobster @@ -0,0 +1,12 @@ +FROM node:14.12 + +RUN apt-get update +RUN npm install http-server -g +COPY . /paper-hn + +WORKDIR /paper-hn +RUN yarn install + +COPY /scripts/main_loop_lobster.sh . + +CMD /paper-hn/main_loop_lobster.sh diff --git a/bin/generate-html-laarc.mjs b/bin/generate-html-laarc.mjs new file mode 100644 index 0000000..9ac4fce --- /dev/null +++ b/bin/generate-html-laarc.mjs @@ -0,0 +1,56 @@ +import {hnget, getitem} from '../lib/hn.mjs' +import {init_titles, title_keyword} from '../lib/keywords.mjs' +import {page_info} from '../lib/page-extract.mjs' +import pug from 'pug' +import fs from 'fs-extra' +import psl from 'psl' +import html2text from 'html2plaintext' + +;(async () => { + await fs.ensureDir('cache/hn/item') + await fs.ensureDir('cache/url') + + await init_titles() + + const stories = [] + const source = 'https://laarrc.firebaseio.com/v0/' + for (const storyid of (await hnget(source, 'topstories')).slice(0, 30)) { + const story = await getitem(source, storyid) + if (story.type !== 'story') continue // Filter out jobs + story.keyword = title_keyword(story.title) + if (story.text) { // Self post + story.url = 'https://www.laarc.io/item?id='+story.id + story.domain = 'laarc.io' + story.paragraph = html2text(story.text.split('

')[0]) + } else { + story.domain = psl.parse(new URL(story.url).hostname).domain + const info = await page_info(story.url) + story.paragraph = info.paragraph + story.image = info.image + } + stories.push(story) + } + + const jobs = [] + const jobstories = await hnget(source, 'jobstories') + if(jobstories != null){ + for (const jobid of jobstories.slice(0, 3)) { + const job = await getitem(source, jobid) + const split = job.title.split(' ') + const splitix = (split.findIndex(w => w.toLowerCase() === 'hiring') || 3)+1 + job.title1 = split.slice(0, splitix).join(' ') + job.title2 = split.slice(splitix).join(' ') + jobs.push(job) + } + } + await fs.writeFile('index.html', pug.renderFile('index.pug', { + stories, + jobs, + date: new Date(1000*Math.max(...stories.map(s => s.time))).toLocaleString('en-US', { + timeZone: 'UTC', + dateStyle: 'full', + timeStyle: 'short', + timeZoneName: 'short', + }), + })) +})().then(null, err => {throw err}) diff --git a/scripts/main_loop.sh b/scripts/main_loop_hn.sh similarity index 100% rename from scripts/main_loop.sh rename to scripts/main_loop_hn.sh diff --git a/scripts/main_loop_lobster.sh b/scripts/main_loop_lobster.sh new file mode 100755 index 0000000..116302a --- /dev/null +++ b/scripts/main_loop_lobster.sh @@ -0,0 +1,16 @@ +#! /bin/bash + + +REFRESH_INTERVAL=${REFRESH_INTERVAL:-300} +cd /paper-hn + +http-server . >http.log 2>&1 & +echo Starting up... > index.html + +while true +do + node --trace-warnings --experimental-modules ./bin/generate-html-laarc.mjs + sleep $REFRESH_INTERVAL + rm cache/hn/*.json +done + From 0fdfcdf8483394a25181635b3eb26f19a93c2247 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sun, 25 Oct 2020 13:54:56 +0100 Subject: [PATCH 08/37] Add lobste.rs feed --- bin/generate-html-hn.mjs | 123 ++++++++++++++++++++++----------------- lib/hn.mjs | 9 +-- lib/keywords.mjs | 2 +- 3 files changed, 75 insertions(+), 59 deletions(-) diff --git a/bin/generate-html-hn.mjs b/bin/generate-html-hn.mjs index 212482b..2cfafc5 100644 --- a/bin/generate-html-hn.mjs +++ b/bin/generate-html-hn.mjs @@ -3,60 +3,75 @@ import{hnget, getitem} from '../lib/hn.mjs' import{ page_info} from '../lib/page-extract.mjs' import pug from 'pug' import fs from 'fs-extra' import psl from 'psl' import html2text from 'html2plaintext' - ; -(async() = - > - { - await fs.ensureDir('cache/hn/item') await fs.ensureDir('cache/url') +;(async () => { + + + const stories = [] + const jobs = [] + const source_urls=['https://hacker-news.firebaseio.com/v0/', 'https://laarrc.firebaseio.com/v0/'] + const story_urls=['https://news.ycombinator.com/item?id=', 'https://www.laarc.io/item?id='] + const story_domains=['news.ycombinator.com','laarc.io'] + const cache_paths=['hacker-news', 'lobster'] + + + for (var i=0; i')[0]) story.image = false - } - else {story.domain = - psl.parse(new URL(story.url).hostname).domain const info = - await page_info(story.url) story.paragraph = - info.paragraph story.image = - info.image} stories.push(story) - } + var storyids=await hnget(source_url, 'topstories',cache_path) + + for (var storyid of (storyids).slice(0, 30)) { + console.log(" Getting:"+source_url+storyid); + var story = await getitem(source_url, storyid, cache_path) + if (story.type !== 'story') continue // Filter out jobs + story.keyword = title_keyword(story.title) + if (story.text) { // Self post + story.url = story_url+story.id + story.domain = story_domain + story.paragraph = html2text(story.text.split('

')[0]) + story.image = false + } else { + story.domain = psl.parse(new URL(story.url).hostname).domain + const info = await page_info(story.url) + story.paragraph = info.paragraph + story.image = info.image + } + stories.push(story) + } + + // for (const jobid of (await hnget(source_url, 'jobstories', cache_path)).slice(0, 3)) { + // const job = await getitem(source_url, jobid, cache_path) + // const split = job.title.split(' ') + // const splitix = (split.findIndex(w => w.toLowerCase() === 'hiring') || 3)+1 + // job.title1 = split.slice(0, splitix).join(' ') + // job.title2 = split.slice(splitix).join(' ') + // jobs.push(job) + // } + } - const jobstories = await hnget(source_url, 'jobstories', - cache_path) if (jobstories != null) { - for (const jobid of jobstories.slice(0, 3)) { - const job = await getitem(source_url, jobid, cache_path) - const split = job.title.split(' ') const splitix = - (split.findIndex(w = > w.toLowerCase() == = 'hiring') || 3) + - 1 job.title1 = split.slice(0, splitix).join(' ') job.title2 = - split.slice(splitix).join(' ') jobs.push(job) - } - } - - await fs.writeFile('index.html', pug.renderFile('index.pug', { - stories, - jobs, - date : new Date(1000 * Math.max(... stories.map(s = > s.time))) - .toLocaleString('en-US', { - timeZone : 'UTC', - dateStyle : 'full', - timeStyle : 'short', - timeZoneName : 'short', - }), - })) - })() - .then(null, err = > {throw err}) + await fs.writeFile('index.html', pug.renderFile('index.pug', { + stories, + jobs, + date: new Date(1000*Math.max(...stories.map(s => s.time))).toLocaleString('en-US', { + timeZone: 'UTC', + dateStyle: 'full', + timeStyle: 'short', + timeZoneName: 'short', + }), + })) +})().then(null, err => {throw err}) diff --git a/lib/hn.mjs b/lib/hn.mjs index 17ee1c7..3dc3570 100644 --- a/lib/hn.mjs +++ b/lib/hn.mjs @@ -1,12 +1,13 @@ import fetch from 'node-fetch' import fs from 'fs-extra' -export async function hnget(source, q) { - const cache = `cache/hn/${q}.json` +export async function hnget(source, q, cache_path) { + const cache = `cache/${cache_path}/${q}.json` if (await fs.exists(cache)) { return fs.readJson(cache) } const url = `${source}${q}.json` + console.log(" --> "+url) const res = await fetch(url) if (!res.ok) { @@ -17,6 +18,6 @@ export async function hnget(source, q) { return ret } -export async function getitem(source,itemid) { - return await hnget(source,`item/${itemid}`) +export async function getitem(source,itemid, cache_path) { + return await hnget(source,`item/${itemid}`, cache_path) } diff --git a/lib/keywords.mjs b/lib/keywords.mjs index 4417b10..5701ce9 100644 --- a/lib/keywords.mjs +++ b/lib/keywords.mjs @@ -34,7 +34,7 @@ async function titles_file() { let tokcount export async function init_titles() { const titles = await titles_file() - for (const storyfile of await fs.readdir('cache/hn/item/')) { + for (const storyfile of await fs.readdir('cache/hacker-news/item/')) { const storyid = storyfile.split('.')[0] const story = await getitem(storyid) if (story.type !== 'story') { From ec1edb6d8ad502940a8fba7676b220ac10fb9ce4 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sun, 25 Oct 2020 14:10:53 +0100 Subject: [PATCH 09/37] Reenable jobs --- bin/generate-html-hn.mjs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/bin/generate-html-hn.mjs b/bin/generate-html-hn.mjs index 2cfafc5..c13ba6b 100644 --- a/bin/generate-html-hn.mjs +++ b/bin/generate-html-hn.mjs @@ -54,14 +54,18 @@ import{hnget, getitem} from '../lib/hn.mjs' import{ stories.push(story) } - // for (const jobid of (await hnget(source_url, 'jobstories', cache_path)).slice(0, 3)) { - // const job = await getitem(source_url, jobid, cache_path) - // const split = job.title.split(' ') - // const splitix = (split.findIndex(w => w.toLowerCase() === 'hiring') || 3)+1 - // job.title1 = split.slice(0, splitix).join(' ') - // job.title2 = split.slice(splitix).join(' ') - // jobs.push(job) - // } + const jobstories = await hnget(source_url, 'jobstories', cache_path) + if(jobstories != null) + { + for (const jobid of jobstories.slice(0, 3)) { + const job = await getitem(source_url, jobid, cache_path) + const split = job.title.split(' ') + const splitix = (split.findIndex(w => w.toLowerCase() === 'hiring') || 3)+1 + job.title1 = split.slice(0, splitix).join(' ') + job.title2 = split.slice(splitix).join(' ') + jobs.push(job) + } + } } await fs.writeFile('index.html', pug.renderFile('index.pug', { From a8bc088604fb0f88b5fb665094060d720120a3e2 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sun, 25 Oct 2020 14:44:03 +0100 Subject: [PATCH 10/37] Reformat, remove superfluous --- DockerfileLobster | 12 -------- bin/generate-html-hn.mjs | 11 ++++--- bin/generate-html-laarc.mjs | 56 ------------------------------------ scripts/main_loop_lobster.sh | 16 ----------- 4 files changed, 7 insertions(+), 88 deletions(-) delete mode 100644 DockerfileLobster delete mode 100644 bin/generate-html-laarc.mjs delete mode 100755 scripts/main_loop_lobster.sh diff --git a/DockerfileLobster b/DockerfileLobster deleted file mode 100644 index 9d26552..0000000 --- a/DockerfileLobster +++ /dev/null @@ -1,12 +0,0 @@ -FROM node:14.12 - -RUN apt-get update -RUN npm install http-server -g -COPY . /paper-hn - -WORKDIR /paper-hn -RUN yarn install - -COPY /scripts/main_loop_lobster.sh . - -CMD /paper-hn/main_loop_lobster.sh diff --git a/bin/generate-html-hn.mjs b/bin/generate-html-hn.mjs index c13ba6b..798fb3c 100644 --- a/bin/generate-html-hn.mjs +++ b/bin/generate-html-hn.mjs @@ -1,7 +1,10 @@ -import{hnget, getitem} from '../lib/hn.mjs' import{ - init_titles, title_keyword} from '../lib/keywords.mjs' import{ - page_info} from '../lib/page-extract.mjs' import pug from 'pug' import fs - from 'fs-extra' import psl from 'psl' import html2text from 'html2plaintext' +import {hnget, getitem} from '../lib/hn.mjs' +import {init_titles, title_keyword} from '../lib/keywords.mjs' +import {page_info} from '../lib/page-extract.mjs' +import pug from 'pug' +import fs from 'fs-extra' +import psl from 'psl' +import html2text from 'html2plaintext' ;(async () => { diff --git a/bin/generate-html-laarc.mjs b/bin/generate-html-laarc.mjs deleted file mode 100644 index 9ac4fce..0000000 --- a/bin/generate-html-laarc.mjs +++ /dev/null @@ -1,56 +0,0 @@ -import {hnget, getitem} from '../lib/hn.mjs' -import {init_titles, title_keyword} from '../lib/keywords.mjs' -import {page_info} from '../lib/page-extract.mjs' -import pug from 'pug' -import fs from 'fs-extra' -import psl from 'psl' -import html2text from 'html2plaintext' - -;(async () => { - await fs.ensureDir('cache/hn/item') - await fs.ensureDir('cache/url') - - await init_titles() - - const stories = [] - const source = 'https://laarrc.firebaseio.com/v0/' - for (const storyid of (await hnget(source, 'topstories')).slice(0, 30)) { - const story = await getitem(source, storyid) - if (story.type !== 'story') continue // Filter out jobs - story.keyword = title_keyword(story.title) - if (story.text) { // Self post - story.url = 'https://www.laarc.io/item?id='+story.id - story.domain = 'laarc.io' - story.paragraph = html2text(story.text.split('

')[0]) - } else { - story.domain = psl.parse(new URL(story.url).hostname).domain - const info = await page_info(story.url) - story.paragraph = info.paragraph - story.image = info.image - } - stories.push(story) - } - - const jobs = [] - const jobstories = await hnget(source, 'jobstories') - if(jobstories != null){ - for (const jobid of jobstories.slice(0, 3)) { - const job = await getitem(source, jobid) - const split = job.title.split(' ') - const splitix = (split.findIndex(w => w.toLowerCase() === 'hiring') || 3)+1 - job.title1 = split.slice(0, splitix).join(' ') - job.title2 = split.slice(splitix).join(' ') - jobs.push(job) - } - } - await fs.writeFile('index.html', pug.renderFile('index.pug', { - stories, - jobs, - date: new Date(1000*Math.max(...stories.map(s => s.time))).toLocaleString('en-US', { - timeZone: 'UTC', - dateStyle: 'full', - timeStyle: 'short', - timeZoneName: 'short', - }), - })) -})().then(null, err => {throw err}) diff --git a/scripts/main_loop_lobster.sh b/scripts/main_loop_lobster.sh deleted file mode 100755 index 116302a..0000000 --- a/scripts/main_loop_lobster.sh +++ /dev/null @@ -1,16 +0,0 @@ -#! /bin/bash - - -REFRESH_INTERVAL=${REFRESH_INTERVAL:-300} -cd /paper-hn - -http-server . >http.log 2>&1 & -echo Starting up... > index.html - -while true -do - node --trace-warnings --experimental-modules ./bin/generate-html-laarc.mjs - sleep $REFRESH_INTERVAL - rm cache/hn/*.json -done - From b7bf240b65851bc85fcc598df19dd94c5578ea28 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sun, 25 Oct 2020 14:45:28 +0100 Subject: [PATCH 11/37] Improve naming --- Dockerfile | 4 ++-- scripts/{main_loop_hn.sh => main_loop.sh} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename scripts/{main_loop_hn.sh => main_loop.sh} (100%) diff --git a/Dockerfile b/Dockerfile index 32f4c2e..5c8be05 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,6 @@ COPY . /paper-hn WORKDIR /paper-hn RUN yarn install -COPY /scripts/main_loop_hn.sh . +COPY /scripts/main_loop.sh . -CMD /paper-hn/main_loop_hn.sh +CMD /paper-hn/main_loop.sh diff --git a/scripts/main_loop_hn.sh b/scripts/main_loop.sh similarity index 100% rename from scripts/main_loop_hn.sh rename to scripts/main_loop.sh From 0d0e8a6ba388d9ce7ae67253363fa0bf58b83c36 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sun, 25 Oct 2020 14:47:26 +0100 Subject: [PATCH 12/37] Remove superfluous --- bin/generate-html-hn.mjs | 3 --- lib/hn.mjs | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/bin/generate-html-hn.mjs b/bin/generate-html-hn.mjs index 798fb3c..f3f2fde 100644 --- a/bin/generate-html-hn.mjs +++ b/bin/generate-html-hn.mjs @@ -34,12 +34,9 @@ import html2text from 'html2plaintext' var story_domain=story_domains[i] var cache_path=cache_paths[i] - console.log("Fetching from:"+source_url); - var storyids=await hnget(source_url, 'topstories',cache_path) for (var storyid of (storyids).slice(0, 30)) { - console.log(" Getting:"+source_url+storyid); var story = await getitem(source_url, storyid, cache_path) if (story.type !== 'story') continue // Filter out jobs story.keyword = title_keyword(story.title) diff --git a/lib/hn.mjs b/lib/hn.mjs index 3dc3570..48b5823 100644 --- a/lib/hn.mjs +++ b/lib/hn.mjs @@ -7,7 +7,7 @@ export async function hnget(source, q, cache_path) { return fs.readJson(cache) } const url = `${source}${q}.json` - console.log(" --> "+url) + const res = await fetch(url) if (!res.ok) { From d851e86fd11ae5015e6f72411818be8be4189b71 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sun, 25 Oct 2020 14:56:33 +0100 Subject: [PATCH 13/37] Recusevly delete all cached *.json files --- scripts/main_loop.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/main_loop.sh b/scripts/main_loop.sh index ca36011..46ee870 100755 --- a/scripts/main_loop.sh +++ b/scripts/main_loop.sh @@ -11,6 +11,7 @@ while true do node --trace-warnings --experimental-modules ./bin/generate-html-hn.mjs sleep $REFRESH_INTERVAL - rm cache/hn/*.json + + find cache/ -name "*.json" -type f -delete done From 2809f8efeed4a0c05a516b33065862c9ab6ac400 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sun, 25 Oct 2020 15:02:16 +0100 Subject: [PATCH 14/37] Improve naming --- README.md | 2 +- bin/{generate-html-hn.mjs => generate-html.mjs} | 0 package.json | 4 ++-- scripts/main_loop.sh | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename bin/{generate-html-hn.mjs => generate-html.mjs} (100%) diff --git a/README.md b/README.md index 74611e2..f24860d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Hacker News front page in the style of a print newspaper. ## How to run ``` yarn install -node ./bin/generate-html-hn.mjs +node ./bin/generate-html.mjs ``` This will create an `index.html` file which you can view. diff --git a/bin/generate-html-hn.mjs b/bin/generate-html.mjs similarity index 100% rename from bin/generate-html-hn.mjs rename to bin/generate-html.mjs diff --git a/package.json b/package.json index 94cc6f9..36ba950 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,6 @@ "url-toolkit": "^2.2.0" }, "scripts": { - "watch": "nodemon -e mjs,pug ./bin/generate-html-hn.mjs" + "watch": "nodemon -e mjs,pug ./bin/generate-html.mjs" } -} \ No newline at end of file +} diff --git a/scripts/main_loop.sh b/scripts/main_loop.sh index 46ee870..0970a75 100755 --- a/scripts/main_loop.sh +++ b/scripts/main_loop.sh @@ -9,7 +9,7 @@ echo Starting up... > index.html while true do - node --trace-warnings --experimental-modules ./bin/generate-html-hn.mjs + node --trace-warnings --experimental-modules ./bin/generate-html.mjs sleep $REFRESH_INTERVAL find cache/ -name "*.json" -type f -delete From d0fa8ade9cfa4d6fb1bd3bfb0005f0faa7975f3e Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Fri, 23 Feb 2024 10:40:03 +0100 Subject: [PATCH 15/37] feat: Use latest node --- Dockerfile | 15 +- bin/generate-html.mjs | 16 +- scripts/main_loop.sh | 3 +- yarn.lock | 1286 ----------------------------------------- 4 files changed, 18 insertions(+), 1302 deletions(-) delete mode 100644 yarn.lock diff --git a/Dockerfile b/Dockerfile index 5c8be05..3a88255 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,15 @@ -FROM node:14.12 +FROM node -RUN apt-get update RUN npm install http-server -g -COPY . /paper-hn -WORKDIR /paper-hn -RUN yarn install +RUN adduser user +USER user + +USER user +WORKDIR /home/user +RUN yarn install --modules-folder=/home/user/node_modules +COPY . . COPY /scripts/main_loop.sh . -CMD /paper-hn/main_loop.sh +CMD /home/user/main_loop.sh diff --git a/bin/generate-html.mjs b/bin/generate-html.mjs index f3f2fde..a5485a2 100644 --- a/bin/generate-html.mjs +++ b/bin/generate-html.mjs @@ -7,22 +7,22 @@ import psl from 'psl' import html2text from 'html2plaintext' ;(async () => { - - + + const stories = [] const jobs = [] const source_urls=['https://hacker-news.firebaseio.com/v0/', 'https://laarrc.firebaseio.com/v0/'] const story_urls=['https://news.ycombinator.com/item?id=', 'https://www.laarc.io/item?id='] const story_domains=['news.ycombinator.com','laarc.io'] const cache_paths=['hacker-news', 'lobster'] - - + + for (var i=0; ihttp.log 2>&1 & echo Starting up... > index.html while true do - node --trace-warnings --experimental-modules ./bin/generate-html.mjs + node --trace-warnings --experimental-modules ./bin/generate-html.mjs sleep $REFRESH_INTERVAL find cache/ -name "*.json" -type f -delete diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 5f5a2cf..0000000 --- a/yarn.lock +++ /dev/null @@ -1,1286 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/helper-validator-identifier@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz#60d9847f98c4cea1b279e005fdb7c28be5412d15" - integrity sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw== - -"@babel/parser@^7.6.0", "@babel/parser@^7.9.6": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.3.tgz#7e71d892b0d6e7d04a1af4c3c79d72c1f10f5315" - integrity sha512-oJtNJCMFdIMwXGmx+KxuaD7i3b8uS7TTFYW/FNG2BT8m+fmGHoiPYoH0Pe3gya07WuFmM5FCDIr1x0irkD/hyA== - -"@babel/types@^7.6.1", "@babel/types@^7.9.6": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.3.tgz#6535e3b79fea86a6b09e012ea8528f935099de8e" - integrity sha512-nZxaJhBXBQ8HVoIcGsf9qWep3Oh3jCENK54V4mRF7qaJabVsAYdbTtmSD8WmAp1R6ytPiu5apMwSXyxB1WlaBA== - dependencies: - "@babel/helper-validator-identifier" "^7.10.3" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - -"@types/color-name@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" - integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== - -"@types/node@*": - version "14.0.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.14.tgz#24a0b5959f16ac141aeb0c5b3cd7a15b7c64cbce" - integrity sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ== - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -acorn@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" - integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== - -ansi-align@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" - integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== - dependencies: - string-width "^3.0.0" - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" - integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== - -ansi-styles@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" - integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== - dependencies: - "@types/color-name" "^1.1.1" - color-convert "^2.0.1" - -anymatch@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" - integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - -assert-never@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/assert-never/-/assert-never-1.2.1.tgz#11f0e363bf146205fb08193b5c7b90f4d1cf44fe" - integrity sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw== - -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -babel-walk@3.0.0-canary-5: - version "3.0.0-canary-5" - resolved "https://registry.yarnpkg.com/babel-walk/-/babel-walk-3.0.0-canary-5.tgz#f66ecd7298357aee44955f235a6ef54219104b11" - integrity sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw== - dependencies: - "@babel/types" "^7.9.6" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -binary-extensions@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" - integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== - -boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - -boxen@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" - integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== - dependencies: - ansi-align "^3.0.0" - camelcase "^5.3.1" - chalk "^3.0.0" - cli-boxes "^2.2.0" - string-width "^4.1.0" - term-size "^2.1.0" - type-fest "^0.8.1" - widest-line "^3.1.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -character-parser@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0" - integrity sha1-x84o821LzZdE5f/CxfzeHHMmH8A= - dependencies: - is-regex "^1.0.3" - -cheerio@1.0.0-rc.2: - version "1.0.0-rc.2" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db" - integrity sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs= - dependencies: - css-select "~1.2.0" - dom-serializer "~0.1.0" - entities "~1.1.1" - htmlparser2 "^3.9.1" - lodash "^4.15.0" - parse5 "^3.0.1" - -cheerio@^1.0.0-rc.3: - version "1.0.0-rc.3" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6" - integrity sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA== - dependencies: - css-select "~1.2.0" - dom-serializer "~0.1.1" - entities "~1.1.1" - htmlparser2 "^3.9.1" - lodash "^4.15.0" - parse5 "^3.0.1" - -chokidar@^3.2.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8" - integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.4.0" - optionalDependencies: - fsevents "~2.1.2" - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -cli-boxes@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" - integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== - -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -compare-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/compare-function/-/compare-function-2.0.0.tgz#b590983ea7b8bae61d6de852f3c4bc05f9dd955c" - integrity sha512-Ruf2bBAZCNynGxVfPLhgRfj5pH9Qc/0H0PFiow5Y9FYD19TtHNmIbS+M/XGDMpcbk5Yt5FqnVkPnkdB46cDuEQ== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -configstore@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" - integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== - dependencies: - dot-prop "^5.2.0" - graceful-fs "^4.1.2" - make-dir "^3.0.0" - unique-string "^2.0.0" - write-file-atomic "^3.0.0" - xdg-basedir "^4.0.0" - -constantinople@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-4.0.1.tgz#0def113fa0e4dc8de83331a5cf79c8b325213151" - integrity sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw== - dependencies: - "@babel/parser" "^7.6.0" - "@babel/types" "^7.6.1" - -crypto-random-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" - integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== - -css-select@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= - dependencies: - boolbase "~1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "~1.0.1" - -css-what@2.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" - integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== - -debug@^2.2.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - -doctypes@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" - integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= - -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -dom-serializer@~0.1.0, dom-serializer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== - dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" - -domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domelementtype@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" - integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domutils@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -dot-prop@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" - integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== - dependencies: - is-obj "^2.0.0" - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -entities@^1.1.1, entities@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - -entities@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" - integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== - -escape-goat@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" - integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -fs-extra@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" - integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^1.0.0" - -fsevents@~2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" - integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== - -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" - integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== - dependencies: - pump "^3.0.0" - -glob-parent@~5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== - dependencies: - is-glob "^4.0.1" - -global-dirs@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201" - integrity sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A== - dependencies: - ini "^1.3.5" - -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: - version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" - integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== - -has-yarn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" - integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -html-entities@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.3.1.tgz#fb9a1a4b5b14c5daba82d3e34c6ae4fe701a0e44" - integrity sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA== - -html2plaintext@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/html2plaintext/-/html2plaintext-2.1.2.tgz#c20b6be07ca449ff82f0c677fca05c6c19e09b18" - integrity sha512-/7rk161q0RFtQhu0F7oU7MFUtqjm2qBrVfoS8EOaHSdRNt72CNNYSV1/wN+TfO2GhgLQdIjPctmiWPX3oRcNFQ== - dependencies: - cheerio "1.0.0-rc.2" - he "1.2.0" - plumb "0.1.0" - -htmlparser2@^3.9.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - -ignore-by-default@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" - integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= - -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -inherits@^2.0.1, inherits@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ini@^1.3.5, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-expression@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-4.0.0.tgz#c33155962abf21d0afd2552514d67d2ec16fd2ab" - integrity sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A== - dependencies: - acorn "^7.1.1" - object-assign "^4.1.1" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-installed-globally@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" - integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== - dependencies: - global-dirs "^2.0.1" - is-path-inside "^3.0.1" - -is-npm@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" - integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-path-inside@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" - integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== - -is-promise@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" - integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== - -is-regex@^1.0.3: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" - integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== - dependencies: - has-symbols "^1.0.1" - -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-yarn-global@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" - integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== - -js-stringify@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" - integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= - -jsonfile@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179" - integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg== - dependencies: - universalify "^1.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -jstransformer@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3" - integrity sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM= - dependencies: - is-promise "^2.0.0" - promise "^7.0.1" - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -latest-version@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" - integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== - dependencies: - package-json "^6.3.0" - -lodash@^4.15.0, lodash@^4.17.13: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -node-fetch@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" - integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== - -nodemon@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.4.tgz#55b09319eb488d6394aa9818148c0c2d1c04c416" - integrity sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ== - dependencies: - chokidar "^3.2.2" - debug "^3.2.6" - ignore-by-default "^1.0.1" - minimatch "^3.0.4" - pstree.remy "^1.1.7" - semver "^5.7.1" - supports-color "^5.5.0" - touch "^3.1.0" - undefsafe "^2.0.2" - update-notifier "^4.0.0" - -nopt@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= - dependencies: - abbrev "1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-url@^4.1.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" - integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== - -nth-check@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - -object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - -package-json@^6.3.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" - integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== - dependencies: - got "^9.6.0" - registry-auth-token "^4.0.0" - registry-url "^5.0.0" - semver "^6.2.0" - -parse5@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" - integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA== - dependencies: - "@types/node" "*" - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -picomatch@^2.0.4, picomatch@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== - -plumb@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/plumb/-/plumb-0.1.0.tgz#4c57790a509692832fdbf10dfaddd7948c5cb574" - integrity sha1-TFd5ClCWkoMv2/EN+t3XlIxctXQ= - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -promise@^7.0.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== - dependencies: - asap "~2.0.3" - -psl@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -pstree.remy@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" - integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== - -pug-attrs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-3.0.0.tgz#b10451e0348165e31fad1cc23ebddd9dc7347c41" - integrity sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA== - dependencies: - constantinople "^4.0.1" - js-stringify "^1.0.2" - pug-runtime "^3.0.0" - -pug-code-gen@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-3.0.1.tgz#ff3b337b100c494ea63ef766091d27f7d73acb7e" - integrity sha512-xJIGvmXTQlkJllq6hqxxjRWcay2F9CU69TuAuiVZgHK0afOhG5txrQOcZyaPHBvSWCU/QQOqEp5XCH94rRZpBQ== - dependencies: - constantinople "^4.0.1" - doctypes "^1.1.0" - js-stringify "^1.0.2" - pug-attrs "^3.0.0" - pug-error "^2.0.0" - pug-runtime "^3.0.0" - void-elements "^3.1.0" - with "^7.0.0" - -pug-error@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-2.0.0.tgz#5c62173cb09c34de2a2ce04f17b8adfec74d8ca5" - integrity sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ== - -pug-filters@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-4.0.0.tgz#d3e49af5ba8472e9b7a66d980e707ce9d2cc9b5e" - integrity sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A== - dependencies: - constantinople "^4.0.1" - jstransformer "1.0.0" - pug-error "^2.0.0" - pug-walk "^2.0.0" - resolve "^1.15.1" - -pug-lexer@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pug-lexer/-/pug-lexer-5.0.0.tgz#0b779e7d8cbf0f103803675be96351942fd9a727" - integrity sha512-52xMk8nNpuyQ/M2wjZBN5gXQLIylaGkAoTk5Y1pBhVqaopaoj8Z0iVzpbFZAqitL4RHNVDZRnJDsqEYe99Ti0A== - dependencies: - character-parser "^2.2.0" - is-expression "^4.0.0" - pug-error "^2.0.0" - -pug-linker@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-4.0.0.tgz#12cbc0594fc5a3e06b9fc59e6f93c146962a7708" - integrity sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw== - dependencies: - pug-error "^2.0.0" - pug-walk "^2.0.0" - -pug-load@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-3.0.0.tgz#9fd9cda52202b08adb11d25681fb9f34bd41b662" - integrity sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ== - dependencies: - object-assign "^4.1.1" - pug-walk "^2.0.0" - -pug-parser@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-6.0.0.tgz#a8fdc035863a95b2c1dc5ebf4ecf80b4e76a1260" - integrity sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw== - dependencies: - pug-error "^2.0.0" - token-stream "1.0.0" - -pug-runtime@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-3.0.0.tgz#d523025fdc0a1efe70929d1fd3a2d24121ffffb6" - integrity sha512-GoEPcmQNnaTsePEdVA05bDpY+Op5VLHKayg08AQiqJBWU/yIaywEYv7TetC5dEQS3fzBBoyb2InDcZEg3mPTIA== - -pug-strip-comments@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz#f94b07fd6b495523330f490a7f554b4ff876303e" - integrity sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ== - dependencies: - pug-error "^2.0.0" - -pug-walk@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-2.0.0.tgz#417aabc29232bb4499b5b5069a2b2d2a24d5f5fe" - integrity sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ== - -pug@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pug/-/pug-3.0.0.tgz#101eecd7a236cd9906e420e17799d4d57f2b7d93" - integrity sha512-inmsJyFBSHZaiGLaguoFgJGViX0If6AcfcElimvwj9perqjDpUpw79UIEDZbWFmoGVidh08aoE+e8tVkjVJPCw== - dependencies: - pug-code-gen "^3.0.0" - pug-filters "^4.0.0" - pug-lexer "^5.0.0" - pug-linker "^4.0.0" - pug-load "^3.0.0" - pug-parser "^6.0.0" - pug-runtime "^3.0.0" - pug-strip-comments "^2.0.0" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pupa@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.0.1.tgz#dbdc9ff48ffbea4a26a069b6f9f7abb051008726" - integrity sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA== - dependencies: - escape-goat "^2.0.0" - -rc@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -readable-stream@^3.1.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@~3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" - integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== - dependencies: - picomatch "^2.2.1" - -registry-auth-token@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479" - integrity sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA== - dependencies: - rc "^1.2.8" - -registry-url@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" - integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== - dependencies: - rc "^1.2.8" - -resolve@^1.15.1: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - dependencies: - path-parse "^1.0.6" - -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" - -safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -semver-diff@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" - integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== - dependencies: - semver "^6.3.0" - -semver@^5.7.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -signal-exit@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== - -string-width@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string-width@^4.0.0, string-width@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -strip-ansi@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== - dependencies: - ansi-regex "^5.0.0" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -supports-color@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" - integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== - dependencies: - has-flag "^4.0.0" - -term-size@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753" - integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -token-stream@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-1.0.0.tgz#cc200eab2613f4166d27ff9afc7ca56d49df6eb4" - integrity sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ= - -touch@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" - integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== - dependencies: - nopt "~1.0.10" - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -undefsafe@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.3.tgz#6b166e7094ad46313b2202da7ecc2cd7cc6e7aae" - integrity sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A== - dependencies: - debug "^2.2.0" - -unique-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" - integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== - dependencies: - crypto-random-string "^2.0.0" - -universalify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" - integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== - -update-notifier@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.0.tgz#4866b98c3bc5b5473c020b1250583628f9a328f3" - integrity sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew== - dependencies: - boxen "^4.2.0" - chalk "^3.0.0" - configstore "^5.0.1" - has-yarn "^2.1.0" - import-lazy "^2.1.0" - is-ci "^2.0.0" - is-installed-globally "^0.3.1" - is-npm "^4.0.0" - is-yarn-global "^0.3.0" - latest-version "^5.0.0" - pupa "^2.0.1" - semver-diff "^3.1.1" - xdg-basedir "^4.0.0" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url-toolkit@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/url-toolkit/-/url-toolkit-2.2.0.tgz#9a57b89f315d4b7dc340e150bcfa548ddf5f5ce9" - integrity sha512-Rde0c9S4fJK3FaHim3DSgdQ8IFrSXcZCpAJo9T7/FA+BoQGhK0ow3mpwGQLJCPYsNn6TstpW7/7DzMpSpz9F9w== - -util-deprecate@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -void-elements@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" - integrity sha1-YU9/v42AHwu18GYfWy9XhXUOTwk= - -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== - dependencies: - string-width "^4.0.0" - -with@^7.0.0: - version "7.0.2" - resolved "https://registry.yarnpkg.com/with/-/with-7.0.2.tgz#ccee3ad542d25538a7a7a80aad212b9828495bac" - integrity sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w== - dependencies: - "@babel/parser" "^7.9.6" - "@babel/types" "^7.9.6" - assert-never "^1.2.1" - babel-walk "3.0.0-canary-5" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -xdg-basedir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" - integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== From df234fc927b7b4dcfafdef5b470dbedeb804be38 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Fri, 23 Feb 2024 10:47:49 +0100 Subject: [PATCH 16/37] fix: Install once we have the package.json --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3a88255..b1ce4ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,8 +8,8 @@ USER user USER user WORKDIR /home/user -RUN yarn install --modules-folder=/home/user/node_modules COPY . . +RUN yarn install --modules-folder=/home/user/node_modules COPY /scripts/main_loop.sh . CMD /home/user/main_loop.sh From d65c89f1e8d0f86e4660e2eefc06a08f578b90a7 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Fri, 23 Feb 2024 11:08:53 +0100 Subject: [PATCH 17/37] fix: Debug --- bin/generate-html.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/generate-html.mjs b/bin/generate-html.mjs index a5485a2..9f3879e 100644 --- a/bin/generate-html.mjs +++ b/bin/generate-html.mjs @@ -11,10 +11,10 @@ import html2text from 'html2plaintext' const stories = [] const jobs = [] - const source_urls=['https://hacker-news.firebaseio.com/v0/', 'https://laarrc.firebaseio.com/v0/'] - const story_urls=['https://news.ycombinator.com/item?id=', 'https://www.laarc.io/item?id='] - const story_domains=['news.ycombinator.com','laarc.io'] - const cache_paths=['hacker-news', 'lobster'] + const source_urls=['https://hacker-news.firebaseio.com/v0/'] + const story_urls=['https://news.ycombinator.com/item?id='] + const story_domains=['news.ycombinator.com'] + const cache_paths=['hacker-news'] for (var i=0; i Date: Fri, 23 Feb 2024 11:15:29 +0100 Subject: [PATCH 18/37] fix: Debug --- lib/page-extract.mjs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/page-extract.mjs b/lib/page-extract.mjs index 1db1621..d89b25a 100644 --- a/lib/page-extract.mjs +++ b/lib/page-extract.mjs @@ -20,7 +20,8 @@ async function gethtml(url) { } const res = await fetch(url) if (!res.ok) { - throw new Error(`HTTP error: ${res.status} for ${url}`) + console.log(`HTTP error. Skipping: ${res.status} for ${url}`) + ret = '' } let ret if (res.headers.get('Content-Type').startsWith('text/html')) { @@ -132,7 +133,7 @@ export async function page_info(url) { normalizeWhitespace: true, }}) $('script').remove() - + return { paragraph: getParagraph($), image: getImage(url, $), From 5ff8b8f02aafc760a3a104160e60ecc8c2ecd29c Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Fri, 23 Feb 2024 11:20:01 +0100 Subject: [PATCH 19/37] fix: Debug --- lib/page-extract.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/page-extract.mjs b/lib/page-extract.mjs index d89b25a..7e621f1 100644 --- a/lib/page-extract.mjs +++ b/lib/page-extract.mjs @@ -21,7 +21,7 @@ async function gethtml(url) { const res = await fetch(url) if (!res.ok) { console.log(`HTTP error. Skipping: ${res.status} for ${url}`) - ret = '' + return '' } let ret if (res.headers.get('Content-Type').startsWith('text/html')) { From f67d5f05ffdb73307969c3111378640e4c066a0a Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Fri, 23 Feb 2024 11:30:02 +0100 Subject: [PATCH 20/37] fix: Debug --- bin/generate-html.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/generate-html.mjs b/bin/generate-html.mjs index 9f3879e..2be8a43 100644 --- a/bin/generate-html.mjs +++ b/bin/generate-html.mjs @@ -71,11 +71,11 @@ import html2text from 'html2plaintext' await fs.writeFile('index.html', pug.renderFile('index.pug', { stories, jobs, - date: new Date(1000*Math.max(...stories.map(s => s.time))).toLocaleString('en-US', { + date: new Intl.DateTimeFormat('en-US', { timeZone: 'UTC', dateStyle: 'full', timeStyle: 'short', timeZoneName: 'short', - }), + }).format(new Date(1000*Math.max(...stories.map(s => s.time)))), })) })().then(null, err => {throw err}) From 3309528937957576fc4b0bfaa658ae55fb847dd1 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Fri, 23 Feb 2024 11:33:42 +0100 Subject: [PATCH 21/37] fix: Debug --- Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Dockerfile b/Dockerfile index b1ce4ae..26c1067 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,4 +12,8 @@ COPY . . RUN yarn install --modules-folder=/home/user/node_modules COPY /scripts/main_loop.sh . +USER root +RUN apt update && apt install vi +USER user + CMD /home/user/main_loop.sh From ee890006805818359b74ee68083cc92d431113d4 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Fri, 23 Feb 2024 11:51:57 +0100 Subject: [PATCH 22/37] fix: Debug --- Dockerfile | 3 ++- bin/generate-html.mjs | 7 +------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 26c1067..0876af0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,8 @@ RUN yarn install --modules-folder=/home/user/node_modules COPY /scripts/main_loop.sh . USER root -RUN apt update && apt install vi +RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes vim +RUN chown -R user:user . USER user CMD /home/user/main_loop.sh diff --git a/bin/generate-html.mjs b/bin/generate-html.mjs index 2be8a43..0838af7 100644 --- a/bin/generate-html.mjs +++ b/bin/generate-html.mjs @@ -71,11 +71,6 @@ import html2text from 'html2plaintext' await fs.writeFile('index.html', pug.renderFile('index.pug', { stories, jobs, - date: new Intl.DateTimeFormat('en-US', { - timeZone: 'UTC', - dateStyle: 'full', - timeStyle: 'short', - timeZoneName: 'short', - }).format(new Date(1000*Math.max(...stories.map(s => s.time)))), + date: new Intl.DateTimeFormat('en', { dateStyle: "medium", timeStyle: "medium" }).format(new Date()), })) })().then(null, err => {throw err}) From 68b268caf05cd24909b1589a0aacaa9859cc93d6 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Fri, 23 Feb 2024 12:05:51 +0100 Subject: [PATCH 23/37] fix: Debug --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index 0876af0..9189cdd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,4 +17,6 @@ RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes vim RUN chown -R user:user . USER user +HEALTHCHECK CMD curl --fail 127.0.0.1:8080 || exit 1 + CMD /home/user/main_loop.sh From cbd4c8939ec97062856b9fc9e1c19a0027295f9d Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Fri, 23 Feb 2024 12:58:02 +0100 Subject: [PATCH 24/37] fix: Debug --- Dockerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9189cdd..0876af0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,4 @@ RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes vim RUN chown -R user:user . USER user -HEALTHCHECK CMD curl --fail 127.0.0.1:8080 || exit 1 - CMD /home/user/main_loop.sh From d59bf88c081ada8ce1ba79bea2c4f5b7f2edb519 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sat, 24 Feb 2024 08:15:31 +0100 Subject: [PATCH 25/37] fix: Debug --- Dockerfile | 8 +++++++- nginx.conf | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 nginx.conf diff --git a/Dockerfile b/Dockerfile index 0876af0..38bf728 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,8 +13,14 @@ RUN yarn install --modules-folder=/home/user/node_modules COPY /scripts/main_loop.sh . USER root -RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes vim +RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes vim nginx +COPY nginx.conf /etc/nginx/nginx.conf +RUN mkdir -p /var/lib/nginx +RUN chown -R user:user /var/lib/nginx +RUN chown -R user:user /var/log/nginx RUN chown -R user:user . + +RUN touch /run/nginx.pid && chown -R user:user /run/nginx.pid USER user CMD /home/user/main_loop.sh diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..8c9be9a --- /dev/null +++ b/nginx.conf @@ -0,0 +1,40 @@ +events { + +} + +http { + include /etc/nginx/conf.d/*.conf; + server { + listen 8080 default_server; + listen [::]:8080 default_server; + server_name _; + #root /usr/share/nginx/html; + + # Load configuration files for the default server block. + include /etc/nginx/default.d/*.conf; + + location / { + root /home/user; + autoindex on; + } + location = /health { + access_log off; + add_header 'Content-Type' 'application/json'; + return 200 '{"status":"OK"}'; + } + location = /ready { + access_log off; + add_header 'Content-Type' 'application/json'; + return 200 '{"status":"OK"}'; + } + + + error_page 404 /404.html; + location = /40x.html { + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + } + } +} From ea2789b5f5d51e461bf58a9d5c3c560fd0cdcf38 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sat, 24 Feb 2024 08:47:21 +0100 Subject: [PATCH 26/37] fix: Debug --- Dockerfile | 2 +- nginx.conf | 4 ++++ scripts/main_loop.sh | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 38bf728..ffabf6b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ RUN yarn install --modules-folder=/home/user/node_modules COPY /scripts/main_loop.sh . USER root -RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes vim nginx +RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes nginx COPY nginx.conf /etc/nginx/nginx.conf RUN mkdir -p /var/lib/nginx RUN chown -R user:user /var/lib/nginx diff --git a/nginx.conf b/nginx.conf index 8c9be9a..2a470ef 100644 --- a/nginx.conf +++ b/nginx.conf @@ -17,6 +17,10 @@ http { root /home/user; autoindex on; } + location /hackernews { + root /home/user; + autoindex on; + } location = /health { access_log off; add_header 'Content-Type' 'application/json'; diff --git a/scripts/main_loop.sh b/scripts/main_loop.sh index 71ebfa6..467b34e 100755 --- a/scripts/main_loop.sh +++ b/scripts/main_loop.sh @@ -3,14 +3,14 @@ REFRESH_INTERVAL=${REFRESH_INTERVAL:-300} -http-server . >http.log 2>&1 & -echo Starting up... > index.html +nginx +echo Building content.. > index.html while true do node --trace-warnings --experimental-modules ./bin/generate-html.mjs sleep $REFRESH_INTERVAL - find cache/ -name "*.json" -type f -delete + #find cache/ -name "*.json" -type f -delete done From 73e3a9206b895946d664b95584751b013bb0c3c6 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sat, 24 Feb 2024 09:05:22 +0100 Subject: [PATCH 27/37] fix: Debug --- nginx.conf | 4 ---- 1 file changed, 4 deletions(-) diff --git a/nginx.conf b/nginx.conf index 2a470ef..8c9be9a 100644 --- a/nginx.conf +++ b/nginx.conf @@ -17,10 +17,6 @@ http { root /home/user; autoindex on; } - location /hackernews { - root /home/user; - autoindex on; - } location = /health { access_log off; add_header 'Content-Type' 'application/json'; From 45b840ec1399ac91ca519600787abd368028ba0c Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sat, 24 Feb 2024 09:43:37 +0100 Subject: [PATCH 28/37] feat: Cronjob for refreshing of cache --- Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ffabf6b..c7c83eb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,9 @@ RUN yarn install --modules-folder=/home/user/node_modules COPY /scripts/main_loop.sh . USER root -RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes nginx +RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes nginx cron +RUN echo '25 5 * * * rm -rf /home/user/cache/hn/*.json' > /tmp/crontab + COPY nginx.conf /etc/nginx/nginx.conf RUN mkdir -p /var/lib/nginx RUN chown -R user:user /var/lib/nginx From 76536eda305fec21162289b76e1f370357d9f8de Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sat, 24 Feb 2024 09:44:52 +0100 Subject: [PATCH 29/37] feat: Timezone --- Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Dockerfile b/Dockerfile index c7c83eb..735138c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,10 @@ USER root RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes nginx cron RUN echo '25 5 * * * rm -rf /home/user/cache/hn/*.json' > /tmp/crontab +ENV TZ=Europe/Vienna +ENV LANG=en_US.UTF-8 \ + LANGUAGE=en_US.UTF-8 + COPY nginx.conf /etc/nginx/nginx.conf RUN mkdir -p /var/lib/nginx RUN chown -R user:user /var/lib/nginx From 04c4f21c13367f6772f0c027eb73f98e3ad96143 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sat, 24 Feb 2024 09:51:28 +0100 Subject: [PATCH 30/37] feat: Cronjob for refreshing of cache --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 735138c..376faef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ COPY /scripts/main_loop.sh . USER root RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes nginx cron -RUN echo '25 5 * * * rm -rf /home/user/cache/hn/*.json' > /tmp/crontab +RUN echo '25 5 * * * rm -rf /home/user/cache/hn/*.json' > /tmp/crontab && cat /tmp/crontab | crontab - ENV TZ=Europe/Vienna ENV LANG=en_US.UTF-8 \ From a85a8e6cace8343e70ea6cf6e24ce370adb29543 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sat, 24 Feb 2024 12:03:02 +0100 Subject: [PATCH 31/37] feat: Docker - Harden --- Dockerfile | 5 +- scripts/harden.sh | 140 +++++++++++++++++++++++++++++++++++++++++++ scripts/main_loop.sh | 2 - 3 files changed, 144 insertions(+), 3 deletions(-) create mode 100755 scripts/harden.sh diff --git a/Dockerfile b/Dockerfile index 376faef..f2f646d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,10 +11,11 @@ WORKDIR /home/user COPY . . RUN yarn install --modules-folder=/home/user/node_modules COPY /scripts/main_loop.sh . +COPY /scripts/harden.sh . USER root RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes nginx cron -RUN echo '25 5 * * * rm -rf /home/user/cache/hn/*.json' > /tmp/crontab && cat /tmp/crontab | crontab - +RUN echo '0 */4 * * * rm -rf /home/user/cache/hn/*.json' > /tmp/crontab && cat /tmp/crontab | crontab - ENV TZ=Europe/Vienna ENV LANG=en_US.UTF-8 \ @@ -27,6 +28,8 @@ RUN chown -R user:user /var/log/nginx RUN chown -R user:user . RUN touch /run/nginx.pid && chown -R user:user /run/nginx.pid + +RUN ./harden.sh user USER user CMD /home/user/main_loop.sh diff --git a/scripts/harden.sh b/scripts/harden.sh new file mode 100755 index 0000000..670614f --- /dev/null +++ b/scripts/harden.sh @@ -0,0 +1,140 @@ +#!/bin/sh + +set -eux + +USER=$1 +rm $0 # Remove self + +# TODO: Needed? +# Ensure strict ownership and perms. +# mkdir -p /home/$USER/.ssh +# chown -R root:root /home/$USER/.ssh +# chmod -R 0444 /home/$USER/.ssh + +# Improve strength of diffie-hellman-group-exchange-sha256 (Custom DH with SHA2). +# See https://stribika.github.io/2015/01/04/secure-secure-shell.html +# +# Columns in the moduli file are: +# Time Type Tests Tries Size Generator Modulus +# +# This file is provided by the openssh package on Fedora. +moduli=/etc/ssh/moduli +if [[ -f ${moduli} ]]; then + cp ${moduli} ${moduli}.orig + awk '$5 >= 2000' ${moduli}.orig > ${moduli} + rm -f ${moduli}.orig +fi + +# Remove existing crontabs, if any. +#rm -fr /var/spool/cron +rm -fr /etc/crontabs +rm -fr /etc/periodic + +# Remove all but a handful of admin commands. +find /usr/sbin ! -type d \ + -a ! -name unix_chkpwd \ + -a ! -name nologin \ + -a ! -name nginx \ + -a ! -name setup-proxy \ + -a ! -name sshd \ + -a ! -name start.sh \ + -delete + +# Remove world-writable permissions. +# This breaks apps that need to write to /tmp, +# such as ssh-agent. +find / -xdev -type d -perm /0002 -exec chmod o-w {} + +find / -xdev -type f -perm /0002 -exec chmod o-w {} + + +# Remove unnecessary user accounts. +sed -i -r '/^('$USER'|root|sshd)/!d' /etc/group +sed -i -r '/^('$USER'|root|sshd)/!d' /etc/passwd + +# Remove interactive login shell for everybody but user. +sed -i -r '/^'$USER':/! s#^(.*):[^:]*$#\1:/sbin/nologin#' /etc/passwd + +sysdirs=" + /bin + /etc + /lib + /sbin + /usr +" + +# Remove apk configs. +find $sysdirs -xdev -regex '.*apk.*' -exec rm -fr {} + + +# Ensure system dirs are owned by root and not writable by anybody else. +find $sysdirs -xdev -type d \ + -exec chown root:root {} \; \ + -exec chmod 0755 {} \; + +# Remove all suid files. +find $sysdirs -xdev -type f -a -perm /4000 -delete + +# Remove all guid files. +find $sysdirs -xdev -type f -a -perm /2000 -a ! -name crontab -delete + +# Remove other programs that could be dangerous. +find $sysdirs -xdev \( \ + -name hexdump -o \ + -name chgrp -o \ + -name chmod -o \ + -name chown -o \ + -name ln -o \ + -name od -o \ + -name strings -o \ + -name su \ + \) -delete + + # Remove init scripts since we do not use them. +rm -fr /etc/init.d +rm -fr /lib/rc +rm -fr /etc/conf.d +rm -fr /etc/inittab +rm -fr /etc/runlevels +rm -fr /etc/rc.conf + +# # Remove kernel tunables since we do not need them. +rm -fr /etc/sysctl* +rm -fr /etc/modprobe.d +rm -fr /etc/modules +rm -fr /etc/mdev.conf +rm -fr /etc/acpi + +# # Remove root homedir since we do not need it. +rm -fr /root + +# # Remove fstab since we do not need it. +rm -f /etc/fstab + +# Remove broken symlinks (because we removed the targets above). +find $sysdirs -xdev -type l -exec test ! -e {} \; -delete + +# Remove almost all commands, all other users + +command_paths=" + /bin + /sbin + /usr/bin + /usr/local/bin + /usr/sbin +" + +# sh necessary for Healthchecks +# rm /bin/sh +# cp /bin/bash /bin/sh + +find $command_paths -xdev \( \ + -name apt -o \ + -name cat -o \ + -name date -o \ + -name id -o \ + -name ldd -o \ + -name ls -o \ + -name pgrep -o \ + -name ps -o \ + -name stty -o \ + -name unix_chkpwd -o \ + -name which \ + \) -delete diff --git a/scripts/main_loop.sh b/scripts/main_loop.sh index 467b34e..d61d962 100755 --- a/scripts/main_loop.sh +++ b/scripts/main_loop.sh @@ -10,7 +10,5 @@ while true do node --trace-warnings --experimental-modules ./bin/generate-html.mjs sleep $REFRESH_INTERVAL - - #find cache/ -name "*.json" -type f -delete done From b1356f9893afd5c4b6ef500644f774519dd0102f Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sat, 24 Feb 2024 17:46:19 +0100 Subject: [PATCH 32/37] feat: Docker - Remove cron, cleanup in main loop --- Dockerfile | 5 +---- bin/generate-html.mjs | 32 +++++++++++++++++++++++++++++--- lib/keywords.mjs | 6 +++--- scripts/harden.sh | 4 ++-- scripts/main_loop.sh | 18 +++++++++++++++--- 5 files changed, 50 insertions(+), 15 deletions(-) diff --git a/Dockerfile b/Dockerfile index f2f646d..7f72ce0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,5 @@ FROM node -RUN npm install http-server -g - RUN adduser user USER user @@ -14,8 +12,7 @@ COPY /scripts/main_loop.sh . COPY /scripts/harden.sh . USER root -RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes nginx cron -RUN echo '0 */4 * * * rm -rf /home/user/cache/hn/*.json' > /tmp/crontab && cat /tmp/crontab | crontab - +RUN apt update && DEBIAN_FRONTEND=noninteractive apt-get install --yes nginx ENV TZ=Europe/Vienna ENV LANG=en_US.UTF-8 \ diff --git a/bin/generate-html.mjs b/bin/generate-html.mjs index 0838af7..d9d6193 100644 --- a/bin/generate-html.mjs +++ b/bin/generate-html.mjs @@ -6,8 +6,32 @@ import fs from 'fs-extra' import psl from 'psl' import html2text from 'html2plaintext' +function getArgs () { + const args = {}; + process.argv + .slice(2, process.argv.length) + .forEach( arg => { + // long arg + if (arg.slice(0,2) === '--') { + const longArg = arg.split('='); + const longArgFlag = longArg[0].slice(2,longArg[0].length); + const longArgValue = longArg.length > 1 ? longArg[1] : true; + args[longArgFlag] = longArgValue; + } + // flags + else if (arg[0] === '-') { + const flags = arg.slice(1,arg.length).split(''); + flags.forEach(flag => { + args[flag] = true; + }); + } + }); + return args; +} + ;(async () => { + const args = getArgs(); const stories = [] const jobs = [] @@ -21,18 +45,20 @@ import html2text from 'html2plaintext' var source_url=source_urls[i] var story_url=story_urls[i] var story_domain=story_domains[i] - var cache_path=cache_paths[i] + var cache_path=args[cache_paths[i]] // i.e. pass --hacker-news=hn (dirty hack but I'm not a JS dev.) await fs.ensureDir(`cache/${cache_path}/item`) await fs.ensureDir('cache/url') - await init_titles() + await init_titles(cache_path) } for (var i=0; i index.html while true do - node --trace-warnings --experimental-modules ./bin/generate-html.mjs + echo "-------------------------------------------" + echo Generating index.html .. > index.html + node --trace-warnings --experimental-modules ./bin/generate-html.mjs --hacker-news=hn + echo "Done." + sleep $REFRESH_INTERVAL + + mkdir -p /home/user/cache/hn2 + rm -rf /home/user/cache/hn2 + echo "-------------------------------------------" + + echo Generating index.html .. > index.html + node --trace-warnings --experimental-modules ./bin/generate-html.mjs --hacker-news=hn2 + rm -rf /home/user/cache/hn + echo "Done." sleep $REFRESH_INTERVAL done From 0ea46c2a3003fbf589b2b3b3f0e9a4a7c174a6a6 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sat, 24 Feb 2024 19:23:36 +0100 Subject: [PATCH 33/37] chore: Docker - Improve verbosity --- scripts/main_loop.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/main_loop.sh b/scripts/main_loop.sh index a0607eb..ce17ae7 100755 --- a/scripts/main_loop.sh +++ b/scripts/main_loop.sh @@ -4,23 +4,22 @@ REFRESH_INTERVAL=${REFRESH_INTERVAL:-3600} nginx +echo Generating index.html .. > index.html while true do echo "-------------------------------------------" - echo Generating index.html .. > index.html - node --trace-warnings --experimental-modules ./bin/generate-html.mjs --hacker-news=hn - echo "Done." + node --trace-warnings --experimental-modules ./bin/generate-html.mjs --hacker-news=hn 2>&1 + echo "Done: $(date)" sleep $REFRESH_INTERVAL mkdir -p /home/user/cache/hn2 rm -rf /home/user/cache/hn2 echo "-------------------------------------------" - echo Generating index.html .. > index.html - node --trace-warnings --experimental-modules ./bin/generate-html.mjs --hacker-news=hn2 + node --trace-warnings --experimental-modules ./bin/generate-html.mjs --hacker-news=hn2 2>&1 rm -rf /home/user/cache/hn - echo "Done." + echo "Done: $(date)" sleep $REFRESH_INTERVAL done From 61e1f3f40faa98573112e724f5598fd24fade0d7 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sat, 24 Feb 2024 19:27:30 +0100 Subject: [PATCH 34/37] chore: Docker - Improve verbosity --- scripts/main_loop.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/main_loop.sh b/scripts/main_loop.sh index ce17ae7..3ae290f 100755 --- a/scripts/main_loop.sh +++ b/scripts/main_loop.sh @@ -9,6 +9,7 @@ echo Generating index.html .. > index.html while true do echo "-------------------------------------------" + echo "Start: $(date)" node --trace-warnings --experimental-modules ./bin/generate-html.mjs --hacker-news=hn 2>&1 echo "Done: $(date)" sleep $REFRESH_INTERVAL @@ -16,6 +17,7 @@ do mkdir -p /home/user/cache/hn2 rm -rf /home/user/cache/hn2 echo "-------------------------------------------" + echo "Start: $(date)" node --trace-warnings --experimental-modules ./bin/generate-html.mjs --hacker-news=hn2 2>&1 rm -rf /home/user/cache/hn From 9448f6256588e5459395dd2b5e0f4905eed1b9aa Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Sat, 24 Feb 2024 19:45:08 +0100 Subject: [PATCH 35/37] chore: Docker - Allow date --- scripts/harden.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/harden.sh b/scripts/harden.sh index 8eb86fe..c6db282 100755 --- a/scripts/harden.sh +++ b/scripts/harden.sh @@ -128,7 +128,6 @@ command_paths=" find $command_paths -xdev \( \ -name apt -o \ -name cat -o \ - -name date -o \ -name id -o \ -name ldd -o \ -name ls -o \ From 5d6159d2230e642be3b77c449fc5d9b7302e1d28 Mon Sep 17 00:00:00 2001 From: Mihai Orange Pi Date: Thu, 17 Oct 2024 14:10:05 +0200 Subject: [PATCH 36/37] chore: Logic - Update to fix breakage due to punycode --- lib/page-extract.mjs | 2 +- package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/page-extract.mjs b/lib/page-extract.mjs index 7e621f1..807cf9b 100644 --- a/lib/page-extract.mjs +++ b/lib/page-extract.mjs @@ -1,7 +1,7 @@ import crypto from 'crypto' import fetch from 'node-fetch' import fs from 'fs-extra' -import cheerio from 'cheerio' +import * as cheerio from "cheerio" import compare from 'compare-function' import URLToolkit from 'url-toolkit' import htmlEntities from 'html-entities' diff --git a/package.json b/package.json index 36ba950..631b3a3 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "fs-extra": "^9.0.1", "html-entities": "^1.3.1", "html2plaintext": "^2.1.2", + "punycode": "^2.3.1", "node-fetch": "^2.6.0", "nodemon": "^2.0.4", "psl": "^1.8.0", From b6dbdb0ebae0c57f36b0cb7cfdc4c3c26fea6714 Mon Sep 17 00:00:00 2001 From: Mihai Galos Date: Tue, 4 Mar 2025 22:08:43 +0100 Subject: [PATCH 37/37] chore: Docker - Timeout generation --- scripts/main_loop.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/main_loop.sh b/scripts/main_loop.sh index 3ae290f..4b010ed 100755 --- a/scripts/main_loop.sh +++ b/scripts/main_loop.sh @@ -10,7 +10,7 @@ while true do echo "-------------------------------------------" echo "Start: $(date)" - node --trace-warnings --experimental-modules ./bin/generate-html.mjs --hacker-news=hn 2>&1 + timeout 600 node --trace-warnings --experimental-modules ./bin/generate-html.mjs --hacker-news=hn 2>&1 echo "Done: $(date)" sleep $REFRESH_INTERVAL @@ -19,7 +19,7 @@ do echo "-------------------------------------------" echo "Start: $(date)" - node --trace-warnings --experimental-modules ./bin/generate-html.mjs --hacker-news=hn2 2>&1 + timeout 600 node --trace-warnings --experimental-modules ./bin/generate-html.mjs --hacker-news=hn2 2>&1 rm -rf /home/user/cache/hn echo "Done: $(date)" sleep $REFRESH_INTERVAL