From 18cc5f69129615850e48a995f7c3406b74d8d2f4 Mon Sep 17 00:00:00 2001 From: Leonardo Bishop Date: Sat, 5 Aug 2023 21:11:48 +0100 Subject: Redesign website --- .env.defaults | 8 +- app/directory.ts | 312 ------- app/index.ts | 38 +- app/middlewares/blogs.ts | 17 + app/middlewares/index.ts | 15 +- app/pages.ts | 87 ++ app/routes/blog/router.ts | 19 + app/routes/page/router.ts | 47 +- app/routes/special/router.ts | 79 -- app/routes/spotify/router.ts | 26 + app/spotify/client.ts | 158 ++++ app/websocket/spotify.ts | 18 + app/wikiparser.ts | 327 ------- package-lock.json | 1461 ++++++++++++++++++++----------- package.json | 7 +- pages/about.wiki | 61 -- pages/blog/steam-deck-workstation.md | 99 +++ pages/contact.html | 59 ++ pages/contact.wiki | 16 - pages/index.html | 42 + pages/index.wiki | 37 - pages/kpnx.wiki | 98 --- pages/now.md | 16 + pages/spotify.html | 21 + pages/template/blog.wiki | 2 - pages/template/incomplete.wiki | 1 - pages/template/sourcecode.wiki | 1 - pages/test.wiki | 9 - static/css/blog.css | 63 ++ static/css/contact.css | 24 + static/css/globalstyles.css | 120 +-- static/css/home.css | 27 + static/css/variables.css | 21 + static/fonts/iosevka-medium.woff2 | Bin 0 -> 1208328 bytes static/image/questcompass2-256.png | Bin 54415 -> 0 bytes static/images/steam-deck-arch.jpg | Bin 0 -> 635559 bytes static/images/steam-deck-gparted.jpg | Bin 0 -> 615514 bytes static/images/steam-deck-partitions.jpg | Bin 0 -> 841262 bytes static/scripts/purge.js | 15 - static/scripts/rebuild.js | 14 - static/scripts/spotify.js | 12 + tsconfig.json | 2 +- views/blog.ejs | 49 ++ views/error.ejs | 8 +- views/index.ejs | 8 +- views/page.ejs | 20 - views/pageinfo.ejs | 83 -- views/partials/head.ejs | 14 + views/partials/header.ejs | 12 - views/partials/navbar.ejs | 7 +- views/purge.ejs | 26 - views/rebuild.ejs | 23 - 52 files changed, 1823 insertions(+), 1806 deletions(-) delete mode 100644 app/directory.ts create mode 100644 app/middlewares/blogs.ts create mode 100644 app/pages.ts create mode 100644 app/routes/blog/router.ts delete mode 100644 app/routes/special/router.ts create mode 100644 app/routes/spotify/router.ts create mode 100644 app/spotify/client.ts create mode 100644 app/websocket/spotify.ts delete mode 100644 app/wikiparser.ts delete mode 100644 pages/about.wiki create mode 100644 pages/blog/steam-deck-workstation.md create mode 100644 pages/contact.html delete mode 100644 pages/contact.wiki create mode 100644 pages/index.html delete mode 100644 pages/index.wiki delete mode 100644 pages/kpnx.wiki create mode 100644 pages/now.md create mode 100644 pages/spotify.html delete mode 100644 pages/template/blog.wiki delete mode 100644 pages/template/incomplete.wiki delete mode 100644 pages/template/sourcecode.wiki delete mode 100644 pages/test.wiki create mode 100644 static/css/blog.css create mode 100644 static/css/contact.css create mode 100644 static/css/home.css create mode 100644 static/css/variables.css create mode 100644 static/fonts/iosevka-medium.woff2 delete mode 100644 static/image/questcompass2-256.png create mode 100644 static/images/steam-deck-arch.jpg create mode 100644 static/images/steam-deck-gparted.jpg create mode 100644 static/images/steam-deck-partitions.jpg delete mode 100644 static/scripts/purge.js delete mode 100644 static/scripts/rebuild.js create mode 100644 static/scripts/spotify.js create mode 100644 views/blog.ejs delete mode 100644 views/page.ejs delete mode 100644 views/pageinfo.ejs create mode 100644 views/partials/head.ejs delete mode 100644 views/partials/header.ejs delete mode 100644 views/purge.ejs delete mode 100644 views/rebuild.ejs diff --git a/.env.defaults b/.env.defaults index 1c11ae4..3dd7039 100644 --- a/.env.defaults +++ b/.env.defaults @@ -1,6 +1,8 @@ PORT=3000 PAGES_DIR=pages -REBUILD_COOLDOWN_MIN=10 -PURGE_COOLDOWN_MIN=10 -PARSER_MAX_RECURSION=20 LOGGING_LEVEL=info + +SPOTIFY_CLIENT_ID= +SPOTIFY_CLIENT_SECRET= +SPOTIFY_AUTH_CODE= +SPOTIFY_REDIRECT_URI= diff --git a/app/directory.ts b/app/directory.ts deleted file mode 100644 index 77acacf..0000000 --- a/app/directory.ts +++ /dev/null @@ -1,312 +0,0 @@ -import * as parser from './wikiparser.js'; -import { readFileSync } from 'fs'; -import glob from 'glob'; -import { logger } from './logger.js' - -/** - * Build a page. - * - * @param path standard name for page - * @returns newly built page, or undefined - */ -export function buildPage(directory: PageDirectory, page: Page) { - const result = parser.parse(directory, page.raw); - const title = result.metadata.displayTitle ?? page.standardName; - const content = `${result.metadata.notitle ? '' : `

${title}

`}${result.html}`; - - page.html = content; - page.buildTime = Date.now(); - page.metadata.includeInNavbar = result.metadata.primary ?? false; - page.metadata.sortOrder = result.metadata.sortOrder ?? -1; - page.metadata.showTitle = !result.metadata.notitle ?? true; - page.metadata.displayTitle = title; -} - -/** - * Convert a page name to a standard name. - * A standard name is the key used by the page directory. - * - * @param name non-standard name for a page - */ -export function convertNameToStandard(name: string): string { - name = name.replace(/[^a-z0-9:]/gi, '_').toLowerCase(); - if (!name.includes(':')) { - name = `main:${name}`; - } - return name; -} - -/** - * Convert a standard name to a file path. - * - * @param name standard name for a page - */ -export function convertStandardToFilePath(name: string): string { - const [first, second] = name.replace('main:', '').split(':'); - const [title, subpage] = ((second) ? second : first).split('.') - const namespace = (second) ? first : undefined - - return `${namespace ? `${namespace}/` : ''}${title}${subpage ? `.${subpage}` : ''}.wiki` -} - -export class PageDirectory { - pages: Record; - primaryPages: Page[]; - pagePath: string; - lastBuild: number; - - constructor(root: string) { - this.lastBuild = 0; - this.pages = {}; - this.pagePath = root; - - this.rebuild(); - } - - /** - * Build this page directory. - * - * @returns whether the directory was built - */ - rebuild(): boolean { - if (this.lastBuild + parseInt(process.env.REBUILD_COOLDOWN_MIN, 10) * 60 * 1000 > Date.now()) { - return false; - } - for (const page in this.pages) { - delete this.pages[page]; - } - - const pages = glob.sync(`**/*.wiki`, { cwd: this.pagePath }) - - // Load page content - pages.forEach(page => { - page = convertNameToStandard(page.replace('.wiki', '').replace('/', ':')); - this.pages[page] = { - standardName: page, - raw: this.loadRaw(page), - buildTime: 0, - metadata: { - dependencies: new Set(), - dependents: new Set(), - errors: [] - } - } - }); - - const dependencyGraph: Record = {}; - - Object.keys(this.pages).forEach(name => dependencyGraph[name] = Array.from(parser.findDependencies(this.pages[name].raw)).map(e => convertNameToStandard(e))); - - // Revursive dependency graph traversal function - function traverseGraph(dependents: string[], current: string, dependencies: string[], recursionCount: number, pages: Record) { - if (recursionCount > parseInt(process.env.PARSER_MAX_RECURSION, 10)) { - throw new RecursionError('max recursion reached'); - } - - dependencies?.forEach(e => { - pages[current]?.metadata.dependencies.add(e) - if (e !== current) { - pages[e]?.metadata.dependents.add(current); - } - }); - - dependencies?.forEach((dependency: string) => { - if (dependencyGraph[dependency]?.length != 0) { - dependents.forEach((dependent: string) => { - if (dependencyGraph[dependency]?.includes(dependent)) { - throw new DependencyError(`circular dependency between ${dependent} and ${dependency}`, [dependent, dependency]); - } - }); - traverseGraph([...dependents, dependency], dependency, dependencyGraph[dependency], recursionCount + 1, pages); - } - }); - } - - // Catch circular dependencies and build dependency tree - Object.keys(dependencyGraph).forEach(name => { - try { - traverseGraph([name], name, dependencyGraph[name], 1, this.pages); - } catch (e) { - if (e instanceof RecursionError) { - this.pages[name].metadata.errors.push({ - identifier: 'max-recursion-reached', - message: `maximum dependency depth of ${process.env.PARSER_MAX_RECURSION} reached` - }) - logger.warn(`max recursion for ${name} reached`) - } else if (e instanceof DependencyError) { - if (e.pages.includes(name)) { - this.pages[name].metadata.errors.push({ - identifier: 'circular-dependency', - message: e.message - }) - logger.warn(`${e.pages[0]} has a circular dependency with ${e.pages[1]}`) - } else { - logger.warn(`transclusions on page ${name} may not resolve due to dependency errors in its dependency tree`) - } - } else { - throw e; - } - } - }); - - function recursiveBulld(pages: Record, current: Page, directory: PageDirectory, buildPage: (directory: PageDirectory, page: Page) => void) { - if (current.metadata.errors.length == 0) { - current.metadata.dependencies.forEach(dependency => { - if (pages[dependency].buildTime == 0) { - recursiveBulld(pages, pages[dependency], directory, buildPage); - } - }); - buildPage(directory, current) - } - } - - // Build pages in order - const primaryPages = []; - Object.keys(this.pages).forEach(name => { - recursiveBulld(this.pages, this.pages[name], this, buildPage); - - if (this.pages[name].metadata.includeInNavbar) { - primaryPages.push(this.pages[name]); - } - }); - - // Sort primary pages - primaryPages.sort((a, b) => { - return a.metadata.sortOrder - b.metadata.sortOrder; - }); - this.primaryPages = primaryPages; - this.lastBuild = Date.now(); - return true; - } - - /** - * Get whether a page exists with this name. - * - * @param name standard name for page - * @returns whether the page exists - */ - exists(name: string): boolean { - return !!this.pages[convertNameToStandard(name)]; - } - - /** - * Get a page. - * - * @param name standard name for page - * @returns page - */ - get(name: string): Page { - name = convertNameToStandard(name); - const page = this.pages[name]; - if (!page) { - return undefined; - } - - return page; - } - - /** - * Get the raw wikitext for a page. - * - * @param name standard name for page - * @returns raw wikitext - */ - getRaw(name: string): string { - name = convertNameToStandard(name); - return this.pages[name]?.raw; - } - - /** - * Purge (rebuild) a page. - * - * @param name standard name for page - * @returns whether the page was rebuilt - */ - purge(name: string): boolean { - name = convertNameToStandard(name); - const page = this.pages[name]; - if (page) { - if (page.buildTime + parseInt(process.env.PURGE_COOLDOWN_MIN, 10) * 60 * 1000 > Date.now()) { - return false; - } else { - // delete this.pages[name]; - // if (this.buildPage(name)) { - // return true; - // } - } - } - return false; - } - - /** - * Get all pages. - * - * @returns all pages - */ - getPages(): Record { - return this.pages; - } - - /** - * Get primary pages. - * - * @param current - * @returns - */ - getPrimaryPages(): Page[] { - return this.primaryPages; - } - - private loadRaw(name: string): string { - name = convertNameToStandard(name); - let data: string; - try { - data = readFileSync(`${this.pagePath}/${convertStandardToFilePath(name)}`, 'utf-8'); - } catch { - return undefined; - } - return data; - } -} - -export type Page = { - html?: string; - raw?: string; - standardName: string; - buildTime: number; - metadata: PageMetadata; -}; - -export type PageMetadata = { - displayTitle?: string; - sortOrder?: number; - showTitle?: boolean; - includeInNavbar?: boolean; - dependencies: Set; - dependents: Set; - errors: PageError[]; -}; - -export type PageError = { - identifier: string; - message: string; -} - -export class DependencyError extends Error { - pages: string[] - - constructor(message: string, pages: string[]) { - super(message); - this.pages = pages; - - Object.setPrototypeOf(this, DependencyError.prototype); - } -} - -export class RecursionError extends Error { - constructor(message: string) { - super(message); - - Object.setPrototypeOf(this, RecursionError.prototype); - } -} diff --git a/app/index.ts b/app/index.ts index 8514380..3558d1f 100644 --- a/app/index.ts +++ b/app/index.ts @@ -1,46 +1,56 @@ -import { PageDirectory } from './directory.js'; import express from 'express'; import dotenv from 'dotenv-defaults'; import * as page from './routes/page/router.js'; -import * as special from './routes/special/router.js'; -import { navbar } from './middlewares/index.js' +import * as blog from './routes/blog/router.js'; import { logger } from './logger.js' +import { PageDirectory } from './pages.js'; +// import { SpotifyClient } from './spotify/client.js'; +// import { WebSocketServer } from 'ws'; +// import * as spotifyauth from './routes/spotify/router.js'; +// import * as spotifyWs from './websocket/spotify.js'; + +// TODO: Figure out Spotify's tedious auth flow dotenv.config() const app = express(); -const directory = new PageDirectory(process.env.PAGES_DIR); - app.set('view engine', 'ejs'); app.set('views', 'views'); -app.use(express.static('static')); - -app.use((req, res, next) => { - res.locals.directory = directory; - next(); -}); +app.use(express.static('static', { + etag: true, + maxAge: '1d' +})); +app.use(blog.router); app.use(page.router); -app.use(special.router); +// app.use(spotifyauth.router); -app.use(navbar, (req, res) => { +app.use((req, res) => { res.render('error.ejs', { code: '404', - navbar: res.locals.navbarHtml }); }); const server = app.listen(process.env.PORT, () => { logger.info(`App listening on port ${process.env.PORT}`); }); +// const websocketServer: WebSocketServer = spotifyWs.createWebsocketServer(server); const exit = () => { logger.info('Stopping server...'); + // websocketServer.clients.forEach(client => { + // client.terminate(); + // }); + // websocketServer.close(); server.close(() => { process.exit(0); }) } +PageDirectory.rebuild('pages'); + +// SpotifyClient.initialise(); + process.on('SIGINT', exit); process.on('SIGTERM', exit); diff --git a/app/middlewares/blogs.ts b/app/middlewares/blogs.ts new file mode 100644 index 0000000..8fd07c6 --- /dev/null +++ b/app/middlewares/blogs.ts @@ -0,0 +1,17 @@ +import { PageDirectory } from "../pages.js"; + +export const blogs = ((req, res, next) => { + let blogs = []; + for (const page of Object.values(PageDirectory.pages)) { + if (page.route.startsWith('blog/')) { + blogs.push(page); + } + } + + blogs.sort((a, b) => { + return b.metadata.date.getTime() - a.metadata.date.getTime(); + }); + + res.locals.blogs = blogs; + next(); +}); diff --git a/app/middlewares/index.ts b/app/middlewares/index.ts index d07726a..81431ca 100644 --- a/app/middlewares/index.ts +++ b/app/middlewares/index.ts @@ -1,18 +1,11 @@ -export const navbar = ((req, res, next) => { - let navbar = ''; - res.locals.directory.primaryPages.forEach(page => { - navbar += ``; - }) - res.locals.navbarHtml = navbar; - next(); -}); +import { PageDirectory } from "../pages.js"; export const page = ((req, res, next) => { - const path = req.params.page ?? 'index'; + const path = req.originalUrl == "/" ? 'index' : req.originalUrl.substring(1); res.locals.path = path; - const page = res.locals.directory.get(path); - + const page = PageDirectory.get(path); + if (!page) { next(); return; diff --git a/app/pages.ts b/app/pages.ts new file mode 100644 index 0000000..3bef4a9 --- /dev/null +++ b/app/pages.ts @@ -0,0 +1,87 @@ +import { readFileSync } from 'fs'; +import glob from 'glob'; +import { logger } from './logger.js' +import { marked } from 'marked'; +import matter from 'gray-matter'; + +export function buildPage(page: Page) { + logger.info(`Building ${page.path}`); + try { + const result = matter(page.raw); + const metadata = result.data; + const html = marked.parse(result.content, { mangle: false, headerIds: false }); + + page.html = html; + page.metadata = metadata; + page.buildTime = Date.now(); + } catch (e) { + logger.error(`Failed to build page ${page.path}: ${e.message}`); + } +} + +export namespace PageDirectory { + export const pages: Record = {}; + export let lastBuild: number; + + export const rebuild = (pagePath: string): boolean => { + for (const page in pages) { + delete pages[page]; + } + + const localPages = glob.sync(`**/*.{md,html}`, { cwd: pagePath }) + + // Load page content + localPages.forEach(page => { + let route = page.replace(/\.[^.]*$/,'') + let name = /[^/]*$/.exec(route)[0]; + let path = `${pagePath}/${page}` + let raw: string; + try { + raw = loadRaw(path); + } catch (e) { + logger.error(`Failed to read page ${path}: ${e.message}`); + return; + } + + pages[route] = { + route: route, + name: name, + path: path, + raw: raw, + buildTime: 0, + metadata: { + title: "A Page" + } + } + }); + + // Build pages + Object.values(pages).forEach(page => buildPage(page)); + + lastBuild = Date.now(); + return true; + } + + export function get(name: string): Page { + const page = pages[name]; + if (!page) { + return undefined; + } + + return page; + } + + function loadRaw(path: string): string { + return readFileSync(`${path}`, 'utf-8'); + } +} + +export type Page = { + html?: string; + raw?: string; + route: string; + name: string; + path: string; + buildTime: number; + metadata: any; +}; diff --git a/app/routes/blog/router.ts b/app/routes/blog/router.ts new file mode 100644 index 0000000..bbd09d5 --- /dev/null +++ b/app/routes/blog/router.ts @@ -0,0 +1,19 @@ +import express from 'express'; +import { page } from '../../middlewares/index.js'; +import { blogs } from '../../middlewares/blogs.js'; + +export const router = express.Router({ mergeParams: true }); + +router.use('/blog/:page?', page); +router.use('/blog/:page?', blogs); + +router.get('/blog/:page?', (req, res, next) => { + let page = res.locals.page; + let index = !page || res.locals.path === 'blog'; + + res.render('blog.ejs', { + index: index, + blogs: res.locals.blogs, + page: page, + }); +}); diff --git a/app/routes/page/router.ts b/app/routes/page/router.ts index dc819f8..5c0a39b 100644 --- a/app/routes/page/router.ts +++ b/app/routes/page/router.ts @@ -1,51 +1,20 @@ import express from 'express'; -import { navbar, page } from '../../middlewares/index.js'; +import { page } from '../../middlewares/index.js'; export const router = express.Router({ mergeParams: true }); -router.use('/:page.wiki', page); router.use('/:page?', page); -router.get('/:page.wiki', (req, res, next) => { - const page = res.locals.page; - - if (!page) { - next(); - return; - } - - res.type('text/plain'); - res.send(page.raw).end(); -}); - -router.get('/:page?', navbar, (req, res, next) => { - const page = res.locals.page; - +router.get('/:page?', (req, res, next) => { + let page = res.locals.page; if (!page) { next(); return; - } - - let html: string; - let title: string; - - if (page.metadata.errors.length != 0) { - html = '
This page could not be built due to the following errors:
    ' - page.metadata.errors.forEach(e => { - html += `
  • ${e.identifier}: ${e.message}
  • ` - }); - html += '
Go home?
' - title = 'Page error' - } else { - html = page.html; - title = page.metadata.displayTitle; } - - res.render('page.ejs', { - navbar: res.locals.navbarHtml, - path: res.locals.path, - content: html, - title: title, - buildTime: new Date(page.buildTime) + + res.render('index.ejs', { + content: page.html, + stylesheets: page.metadata.stylesheets, + scripts: page.metadata.scripts, }); }); diff --git a/app/routes/special/router.ts b/app/routes/special/router.ts deleted file mode 100644 index 2015a35..0000000 --- a/app/routes/special/router.ts +++ /dev/null @@ -1,79 +0,0 @@ -import express from 'express'; -import { navbar, page } from '../../middlewares/index.js'; -import { logger } from './../../logger.js' - -export const router = express.Router({ mergeParams: true }); - -router.use('/special/purge/:page?', page); -router.use('/special/purge/:page/confirm', page); - -router.get('/special/purge/:page?', navbar, (req, res, next) => { - const page = res.locals.page; - - if (!page) { - next(); - return; - } - - res.render('purge.ejs', { - navbar: res.locals.navbarHtml, - page: res.locals.path, - buildTime: new Date(page.buildTime) ?? 'never', - buildTimeRelative: Math.round((Date.now() - page.buildTime) / 1000 / 60) - }); -}); - -router.get('/special/purge/:page/confirm', (req, res, next) => { - const page = res.locals.page; - - if (!page) { - next(); - return; - } - - logger.info(`Purge for page ${page.standardName} requested by ${req.headers['x-forwarded-for'] || req.socket.remoteAddress }`) - if (res.locals.directory.purge(res.locals.path)) { - res.status(200).send(); - } else { - res.status(429).send(); - } -}); - -router.use('/special/info/:page?', page); - -router.get('/special/info/:page?', navbar, (req, res, next) => { - const page = res.locals.page; - - if (!page) { - next(); - return; - } - - res.render('pageinfo.ejs', { - navbar: res.locals.navbarHtml, - standardName: page.standardName, - displayTitle: page.metadata.displayTitle, - buildTime: page.buildTime, - primary: page.metadata.includeInNavbar, - showTitle: page.metadata.showTitle, - sortOrder: page.metadata.sortOrder, - dependencies: page.metadata.dependencies, - dependents: page.metadata.dependents, - errors: page.metadata.errors, - }); -}); - -router.get('/special/rebuild', navbar, (req, res) => { - res.render('rebuild.ejs', { - navbar: res.locals.navbarHtml - }); -}); - -router.get('/special/rebuild/confirm', (req, res) => { - logger.info(`Directory rebuild requested by ${req.headers['x-forwarded-for'] || req.socket.remoteAddress }`) - if (res.locals.directory.rebuild()) { - res.status(200).send(); - } else { - res.status(429).send(); - } -}); diff --git a/app/routes/spotify/router.ts b/app/routes/spotify/router.ts new file mode 100644 index 0000000..faf8f6d --- /dev/null +++ b/app/routes/spotify/router.ts @@ -0,0 +1,26 @@ +import express from 'express'; + +export const router = express.Router({ mergeParams: true }); + +router.get('/spotify/auth', (req, res, next) => { + let scope = 'user-read-currently-playing'; + let params = new URLSearchParams(); + params.append('response_type', 'code'); + params.append('client_id', process.env.SPOTIFY_CLIENT_ID); + params.append('scope', scope); + params.append('redirect_uri', process.env.SPOTIFY_REDIRECT_URI); + + res.redirect('https://accounts.spotify.com/authorize?' + params.toString()); +}); + +router.get('/spotify/auth/callback', (req, res, next) => { + if (req.query.error) { + res.send('Error: ' + req.query.error); + return; + } + if (!req.query.code) { + res.send('No code'); + return; + } + res.send('Your authentication code: ' + req.query.code); +}); diff --git a/app/spotify/client.ts b/app/spotify/client.ts new file mode 100644 index 0000000..2cdf527 --- /dev/null +++ b/app/spotify/client.ts @@ -0,0 +1,158 @@ +import axios from 'axios'; +import { logger } from '../logger.js'; +import { WebSocket } from 'ws'; + +export namespace SpotifyClient { + let clients = new Set(); + let interval: NodeJS.Timeout; + + let acceptingClients = false; + let authenticationFailed = false; + + let accessToken: string; + let refreshToken: string; + + export const addClient = (client: WebSocket) => { + if (acceptingClients) { + clients.add(client); + } else { + client.close(); + } + } + + const apiTokenUrl = 'https://accounts.spotify.com/api/token'; + + const spotifyClientHeaders = { + 'Authorization': 'Basic ' + Buffer.from(process.env.SPOTIFY_CLIENT_ID + ':' + process.env.SPOTIFY_CLIENT_SECRET).toString('base64'), + 'Content-Type': 'application/x-www-form-urlencoded', + } + + const handleApiError = (err: any, verb: string) => { + if (err.response?.data?.error) { + logger.error(`Failed to ${verb} access token: ${err.message}: ${err.response.data.error}`); + } else { + logger.error(`Failed to get access token: ${err.message} (${err.response.status} ${err.response.statusText} ${err.response.data.error})`); + } + accessToken = undefined; + refreshToken = undefined; + } + + export const requestAccessToken = async () => { + logger.info('Requesting access token from Spotify'); + await axios.post(apiTokenUrl, { + grant_type: 'authorization_code', + code: process.env.SPOTIFY_AUTH_CODE, + redirect_uri: process.env.SPOTIFY_REDIRECT_URI, + }, + { headers: spotifyClientHeaders, + }).then(res => { + logger.info('Authenticated with Spotify'); + accessToken = res.data.access_token; + }).catch(err => { + handleApiError(err, 'request'); + }); + } + + export const refreshAccessToken = async () => { + logger.info('Refreshing access token from Spotify'); + await axios.post(apiTokenUrl, { + grant_type: 'refresh_token', + refresh_token: refreshToken, + }, + { headers: spotifyClientHeaders, + }).then(res => { + logger.info('Refreshed access token from Spotify'); + accessToken = res.data.access_token; + }).catch(err => { + handleApiError(err, 'refresh'); + }); + } + + + export const initialise = async () => { + if (!accessToken) { + await requestAccessToken(); + if (!accessToken) { + logger.error('Failed to get access token, giving up permanently'); + authenticationFailed = true; + return; + } + } + await updateTimeout(); + acceptingClients = true; + } + + const updateTimeout = async () => { + await update(); + interval = setTimeout(updateTimeout, 5000); + } + + export const update = async () => { + if (authenticationFailed) { + return; + } + clients.forEach(client => { + if (client.readyState !== WebSocket.OPEN) { + clients.delete(client); + } + }); + if (clients.size === 0) { + return; + } + await axios.get('https://api.spotify.com/v1/me/player/currently-playing', { + headers: { + 'Authorization': 'Bearer ' + accessToken, + } + }).then(async (res) => { + if (res.status === 401) { + logger.info('Access token expired, refreshing'); + await refreshAccessToken(); + if (!accessToken) { + authenticationFailed = true; + logger.error('Failed to get access token, giving up permanently'); + stop(); + return; + } + await update(); + return; + } + if (res.status !== 200) { + logger.error(`Failed to get current song: ${res.status} ${res.statusText}`); + return; + } + try { + let song = res.data.item.name; + let duration = res.data.item.duration_ms; + let artist = res.data.item.artists[0].name; + let time = res.data.progress_ms; + let album = res.data.item.album.name; + let albumImage = res.data.item.album.images[0].url; + clients.forEach(client => { + client.send(JSON.stringify({ + song: song, + artist: artist, + time: time, + duration: duration, + album: album, + albumImage: albumImage, + })); + }); + } catch (err) { + logger.error(`Failed to parse and send current song: ${err.message}`); + } + }).catch(err => { + if (err.response?.data?.error?.message) { + logger.error(`Failed to get current song: ${err.message}: ${err.response.data.error.message}`); + } else { + logger.error(`Failed to get current song: ${err.message} (${err.response.status} ${err.response.statusText} ${err.response.data.error})`); + } + }); + } + + export const stop = () => { + clearInterval(interval); + acceptingClients = false; + clients.forEach(client => client.close()); + } + +} diff --git a/app/websocket/spotify.ts b/app/websocket/spotify.ts new file mode 100644 index 0000000..4b81fe0 --- /dev/null +++ b/app/websocket/spotify.ts @@ -0,0 +1,18 @@ +import { Server } from 'http'; +import { WebSocketServer } from 'ws'; +import { SpotifyClient } from '../spotify/client.js'; + +export const createWebsocketServer = (server: Server): WebSocketServer => { + const wss = new WebSocketServer({ noServer: true }); + server.on('upgrade', (req, socket, head) => { + wss.handleUpgrade(req, socket, head, (ws) => { + wss.emit('connection', ws, req) + }) + }) + + wss.on('connection', (ws) => { + SpotifyClient.addClient(ws); + }); + + return wss; +} diff --git a/app/wikiparser.ts b/app/wikiparser.ts deleted file mode 100644 index c131a22..0000000 --- a/app/wikiparser.ts +++ /dev/null @@ -1,327 +0,0 @@ -/* - * This file is a modified version of Nixinova/Wikity, whose license is given below: - * Original: https://www.npmjs.com/package/wikity - * - * > ISC License - * > - * > Copyright Β© 2021 Nixinova - * > - * > Permission to use, copy, modify, and/or distribute this software for any purpose with or - * > without fee is hereby granted, provided that the above copyright notice and this - * > permission notice appear in all copies. - * > - * > The software is provided "as is" and the author disclaims all warranties with regard to - * > this software including all implied warranties of merchantability and fitness. In no - * > event shall the author be liable for any special, direct, indirect, or consequential - * > damages or any damages whatsoever resulting from loss of use, data or profits, whether - * > in an action of contract, negligence or other tortious action, arising out of or in - * > connection with the use or performance of this software. - * - * Additonally, this project and my modifications are also licensed under the ISC license. - */ -import dateFormat from 'dateformat'; -import htmlEscape from 'escape-html'; -import { PageDirectory } from './directory'; - -export class Result { - public html: string; - public metadata: any; - - constructor(html: string, metadata: any) { - this.html = html; - this.metadata = metadata; - } -} - -const re = (regex, flag = 'mgi') => { - return RegExp(regex.replace(/ /g, '').replace(/\|\|.+?\|\|/g, ''), flag); -}; -const r = String.raw; -const arg = r`\s*([^|}]+?)\s*`; - -export function findDependencies(data: string): Set { - const pages = new Set(); - - let outText = data; - for (let l = 0, last = ''; l < parseInt(process.env.PARSER_MAX_RECURSION, 10); l++) { - if (last === outText) break; last = outText; - - outText = outText - // Remove non-template magic words - .replace(re(r`<(/?) \s* (?= script|link|meta|iframe|frameset|object|embed|applet|form|input|button|textarea )`), '<$1') - .replace(re(r`(?<= <[^>]+ ) (\bon(\w+))`), 'data-$2') - .replace(//g, '') - .replace(re(r`{{ \s* displayTitle: ([^}]+) }}`), '') - .replace(re(r`{{ \s* navbarSortOrder: ([^}]+) }}`), '') - .replace(re(r`{{ \s* ! \s* }}`), '|') - .replace(re(r`{{ \s* = \s* }}`), '=') - .replace(re(r`{{ \s* [Rr]eflist \s* }}`), '') - .replace(re(r`{{ \s* #? urlencode: ${arg} }}`), '') - .replace(re(r`{{ \s* #? urldecode: ${arg} }}`), '') - .replace(re(r`{{ \s* #? lc: ${arg} }}`), '') - .replace(re(r`{{ \s* #? uc: ${arg} }}`), '') - .replace(re(r`{{ \s* #? lcfirst: ${arg} }}`), '') - .replace(re(r`{{ \s* #? ucfirst: ${arg} }}`), '') - .replace(re(r`{{ \s* #? len: ${arg} }}`), '') - .replace(re(r`{{ \s* #? pos: ${arg} \|${arg} (?: \s*\|${arg} )? }}`), '') - .replace(re(r`{{ \s* #? sub: ${arg} \|${arg} (?:\|${arg})? }}`), '') - .replace(re(r`{{ \s* #? padleft: ${arg} \|${arg} \|${arg} }}`), '') - .replace(re(r`{{ \s* #? padright: ${arg} \|${arg} \|${arg} }}`), '') - .replace(re(r`{{ \s* #? replace: ${arg} \|${arg} \|${arg} }}`), '') - .replace(re(r`{{ \s* #? explode: ${arg} \|${arg} \|${arg} }}`), '') - .replace(re(r`{{ \s* (#\w+) \s* : \s* ( [^{}]+ ) \s* }} ( ?!} )`), '') - - // Templates: {{template}} - .replace(re(r`{{ \s* ([^#}|]+?) (\|[^}]+)? }} (?!})`), (_, title, params = '') => { - if (/{{/.test(params)) return _; - const page = title.includes(':') ? title : `Template:${title}` - pages.add(page); - return ''; - }) - } - return pages; -} - -export function parse(directory: PageDirectory, data: string): Result { - const vars = {}; - const metadata: any = {}; - const nowikis = []; - const refs = []; - - let nowikiCount = 0; - let rawExtLinkCount = 0; - let refCount = 0; - - let outText = data; - - for (let l = 0, last = ''; l < parseInt(process.env.PARSER_MAX_RECURSION, 10); l++) { - if (last === outText) break; last = outText; - - outText = outText - - // Nowiki: - .replace(re(r` ([^]+?) `), (_, m) => `%NOWIKI#${nowikis.push(m), nowikiCount++}%`) - - // Sanitise unacceptable HTML - .replace(re(r`<(/?) \s* (?= script|link|meta|iframe|frameset|object|embed|applet|form|input|button|textarea )`), '<$1') - .replace(re(r`(?<= <[^>]+ ) (\bon(\w+))`), 'data-$2') - - // Comments: - .replace(//g, '') - - // Lines: ---- - .replace(/^-{4,}/gm, '
') - - // Metadata: displayTitle, __NOTOC__, etc - .replace(re(r`{{ \s* displayTitle: ([^}]+) }}`), (_, title) => (metadata.displayTitle = title, '')) - .replace(re(r`{{ \s* navbarSortOrder: ([^}]+) }}`), (_, order) => (metadata.sortOrder = parseInt(order, 10), '')) - .replace(re(r`__NOINDEX__`), () => (metadata.noindex = true, '')) - .replace(re(r`__NOTOC__`), () => (metadata.notoc = true, '')) - .replace(re(r`__FORCETOC__`), () => (metadata.toc = true, '')) - .replace(re(r`__TOC__`), () => (metadata.toc = true, '')) - .replace(re(r`__PRIMARY__`), () => (metadata.primary = true, '')) - .replace(re(r`__NOTITLE__`), () => (metadata.notitle = true, '')) - - // Magic words: {{!}}, {{reflist}}, etc - .replace(re(r`{{ \s* ! \s* }}`), '|') - .replace(re(r`{{ \s* = \s* }}`), '=') - .replace(re(r`{{ \s* [Rr]eflist \s* }}`), '') - - // String functions: {{lc:}}, {{ucfirst:}}, {{len:}}, etc - .replace(re(r`{{ \s* #? urlencode: ${arg} }}`), (_, m) => encodeURI(m)) - .replace(re(r`{{ \s* #? urldecode: ${arg} }}`), (_, m) => decodeURI(m)) - .replace(re(r`{{ \s* #? lc: ${arg} }}`), (_, m) => m.toLowerCase()) - .replace(re(r`{{ \s* #? uc: ${arg} }}`), (_, m) => m.toUpperCase()) - .replace(re(r`{{ \s* #? lcfirst: ${arg} }}`), (_, m) => m[0].toLowerCase() + m.substr(1)) - .replace(re(r`{{ \s* #? ucfirst: ${arg} }}`), (_, m) => m[0].toUpperCase() + m.substr(1)) - .replace(re(r`{{ \s* #? len: ${arg} }}`), (_, m) => m.length) - .replace(re(r`{{ \s* #? pos: ${arg} \|${arg} (?: \s*\|${arg} )? }}`), (_, find, str, n = 0) => find.substr(n).indexOf(str)) - .replace(re(r`{{ \s* #? sub: ${arg} \|${arg} (?:\|${arg})? }}`), (_, str, from, len) => str.substr(+from - 1, +len)) - .replace(re(r`{{ \s* #? padleft: ${arg} \|${arg} \|${arg} }}`), (_, str, n, char) => str.padStart(+n, char)) - .replace(re(r`{{ \s* #? padright: ${arg} \|${arg} \|${arg} }}`), (_, str, n, char) => str.padEnd(+n, char)) - .replace(re(r`{{ \s* #? replace: ${arg} \|${arg} \|${arg} }}`), (_, str, find, rep) => str.split(find).join(rep)) - .replace(re(r`{{ \s* #? explode: ${arg} \|${arg} \|${arg} }}`), (_, str, delim, pos) => str.split(delim)[+pos]) - - // Parser functions: {{#if:}}, {{#switch:}}, etc - .replace(re(r`{{ \s* (#\w+) \s* : \s* ( [^{}]+ ) \s* }} ( ?!} )`), (_, name, content) => { - if (/{{\s*#/.test(content)) return _; - const args = content.trim().split(/\s*\|\s*/); - switch (name) { - case '#if': - return (args[0] ? args[1] : args[2]) || ''; - case '#ifeq': - return (args[0] === args[1] ? args[2] : args[3]) || ''; - case '#vardefine': - vars[args[0]] = args[1] || ''; - return ''; - case '#var': - if (re(r`{{ \s* #vardefine \s* : \s* ${args[0]}`).test(outText)) return _; // wait until var is set - return vars[args[0]] || args[1] || ''; - case '#switch': - return args.slice(1) - .map(arg => arg.split(/\s*=\s*/)) - .filter(duo => args[0] === duo[0].replace('#default', args[0]))[0][1]; - case '#time': - case '#date': - case '#datetime': - return dateFormat(args[1] ? new Date(args[1]) : new Date(), args[0]); - } - }) - - // Templates: {{template}} - .replace(re(r`{{ \s* ([^#}|]+?) (\|[^}]+)? }} (?!})`), (_, title, params = '') => { - if (/{{/.test(params)) return _; - const page = title.includes(':') ? title : `Template:${title}` - - // Retrieve template content - const content = directory.get(page); - if (!content?.html) { - return `Template:${title}`; - } - - // Remove non-template sections - let raw = content.raw - .replace(/.*?<\/noinclude>/gs, '') - .replace(/.*<(includeonly|onlyinclude)>|<\/(includeonly|onlyinclude)>.*/gs, ''); - - // Substitite arguments - const argMatch = (arg) => re(r`{{{ \s* ${arg} (?:\|([^}]*))? \s* }}}`); - const args = params.split('|').slice(1); - for (const i in args) { - const parts = args[i].split('='); - const [arg, val] = parts[1] ? [parts[0], ...parts.slice(1)] : [(+i + 1) + '', parts[0]]; - raw = raw.replace(argMatch(arg), (_, m) => val || m || ''); - } - for (let i = 1; i <= 10; i++) { - raw = raw.replace(argMatch(arg), '$2'); - } - - return raw; - }) - - // Images: [[File:Image.png|options|caption]] - .replace(re(r`\[\[ (?:File|Image): (.+?) (\|.+?)? \]\]`), (_, file, params) => { - if (/{{/.test(params)) return _; - const path = file.trim().replace(/ /g, '_'); - let caption = ''; - const imageData: any = {}; - const imageArgs = params?.split('|').map((arg) => arg.replace(/"/g, '"')); - if (imageArgs) { - for (const param of imageArgs) { - if (['left', 'right', 'center', 'none'].includes(param)) { - imageData.float = param; - } - if (['baseline', 'sub', 'super', 'top', 'text-bottom', 'middle', 'bottom', 'text-bottom'].includes(param)) { - imageData.align = param; - } - else if (['border', 'frameless', 'frame', 'framed', 'thumb', 'thumbnail'].includes(param)) { - imageData.type = { framed: 'frame', thumbnail: 'thumb' }[param] || param; - if (imageData.type === 'thumb') imageData.hasCaption = true; - } - else if (param.endsWith('px')) { - param.replace(/(?:(\w+)?(x))?(\w+)px/, (_, size1, auto, size2) => { - if (size1) Object.assign(imageData, { width: size1, height: size2 }); - else if (auto) Object.assign(imageData, { width: 'auto', height: size2 }); - else Object.assign(imageData, { width: size2, height: 'auto' }); - return ''; - }); - } - else if (param.startsWith('upright=')) { - imageData.width = +param.replace('upright=', '') * 300; - } - else if (param.startsWith('link=')) { - imageData.link = param.replace('link=', ''); - } - else if (param.startsWith('alt=')) { - imageData.alt = param.replace('alt=', ''); - } - else if (param.startsWith('style=')) { - imageData.style = param.replace('style=', ''); - } - else if (param.startsWith('class=')) { - imageData.class = param.replace('class=', ''); - } - else { - caption = param; - } - } - } - let content = ` -
- ${imageData.alt || file} - ${imageData.hasCaption ? `
${caption}
` : ''} -
- `; - if (imageData.link) content = `${content}`; - return content; - }) - - // Markup: '''bold''' and '''italic''' - .replace(re(r`''' ([^']+?) '''`), '$1') - .replace(re(r`'' ([^']+?) ''`), '$1') - - // Headings: ==heading== - .replace(re(r`^ (=+) \s* (.+?) \s* \1 \s* $`), (_, lvl, txt) => `${txt}`) - - // Internal links: [[Page]] and [[Page|Text]] - .replace(re(r`\[\[ ([^\]|]+?) \]\]`), '$1') - .replace(re(r`\[\[ ([^\]|]+?) \| ([^\]]+?) \]\]`), '$2') - .replace(re(r`()([a-z]+)`), '$2$1') - - // External links: [href Page] and just [href] - .replace(re(r`\[ ((?:\w+:)?\/\/ [^\s\]]+) (\s [^\]]+?)? \]`), (_, href, txt) => `${txt || '[' + (++rawExtLinkCount) + ']'}`) - - // Bulleted list: *item - .replace(re(r`^ (\*+) (.+?) $`), (_, lvl, txt) => `${'
    '.repeat(lvl.length)}
  • ${txt}
  • ${'
'.repeat(lvl.length)}`) - .replace(re(r` (\s*?)
    `), '$1') - - // Numbered list: #item - .replace(re(r`^ (#+) (.+?) $`), (_, lvl, txt) => `${'
      '.repeat(lvl.length)}
    1. ${txt}
    2. ${'
    '.repeat(lvl.length)}`) - .replace(re(r` (\s*?)
      `), '$1') - - // Definition list: ;head, :item - .replace(re(r`^ ; (.+) $`), '
      $1
      ') - .replace(re(r`^ (:+) (.+?) $`), (_, lvl, txt) => `${'
      '.repeat(lvl.length)}
      ${txt}
      ${'
      '.repeat(lvl.length)}`) - .replace(re(r` (\s*?)
      `), '$1') - - // Tables: {|, |+, !, |-, |, |} - .replace(re(r`^ \{\| (.*?) $`), (_, attrs) => ``) - .replace(re(r`^ ! ([^]+?) (?= \n^[!|] )`), (_, content) => ``) - .replace(re(r`^ \|\+ (.*?) $`), (_, content) => ``) - .replace(re(r`^ \|[^-+}] ([^]*?) (?= \n^[!|] )`), (_, content) => ``) - .replace(re(r`^ \|- (.*?) $`), (_, attrs) => ``) - .replace(re(r`^ \|\}`), '
      ${content}
      ${content}
      ${content}
      ') - - // References: , - .replace(re(r` (.+?) `), (_, text) => { - refs.push(text); - refCount++; - return `[${refCount}]`; - }) - .replace(re(r``), '
        ' + refs.map((ref, i) => - `
      1. ↑ ${ref}
      2. `).join('\n') + '
      ' - ) - - // Nonstandard: ``code`` and ```code blocks``` - .replace(re(r` \`\`\` ([^\`]+?) \`\`\` `), '
      $1
      ') - .replace(re(r`
       ([^\`]+?) 
      `), '
      $1
      ') - - // Spacing - .replace(/(\r?\n){2}/g, '\n

      \n') - - // Restore nowiki contents - .replace(/%NOWIKI#(\d+)%/g, (_, n) => htmlEscape(nowikis[n])); - } - metadata.buildTime = new Date(); - - const result = new Result(outText, metadata); - return result; -} diff --git a/package-lock.json b/package-lock.json index 4e52a2a..a210bf0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,15 +13,20 @@ "@types/escape-html": "^1.0.1", "@types/express": "^4.17.13", "@types/glob": "^7.2.0", + "axios": "^1.4.0", "dateformat": "^5.0.2", "dotenv-defaults": "^3.0.0", "ejs": "^3.1.6", "escape-html": "^1.0.3", "express": "^4.17.1", "glob": "^7.2.0", - "winston": "^3.3.3" + "gray-matter": "^4.0.3", + "marked": "^6.0.0", + "winston": "^3.3.3", + "ws": "^8.13.0" }, "devDependencies": { + "@types/ws": "^8.5.4", "@typescript-eslint/eslint-plugin": "^5.7.0", "@typescript-eslint/parser": "^5.7.0", "eslint": "^8.5.0" @@ -264,6 +269,15 @@ "@types/node": "*" } }, + "node_modules/@types/ws": { + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", + "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.7.0.tgz", @@ -491,12 +505,12 @@ } }, "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { "node": ">= 0.6" @@ -558,16 +572,35 @@ } }, "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansi-styles/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, + "node_modules/ansi-styles/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -589,9 +622,24 @@ } }, "node_modules/async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } }, "node_modules/balanced-match": { "version": "1.0.2", @@ -599,23 +647,26 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/brace-expansion": { @@ -640,13 +691,25 @@ } }, "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { "node": ">= 0.8" } }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -657,16 +720,18 @@ } }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/color": { @@ -717,34 +782,45 @@ "text-hex": "1.0.x" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dependencies": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" }, "engines": { "node": ">= 0.6" } }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { "node": ">= 0.6" } @@ -790,18 +866,30 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, "node_modules/dir-glob": { "version": "3.0.1", @@ -846,14 +934,14 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/ejs": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", - "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", "dependencies": { - "jake": "^10.6.1" + "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" @@ -870,7 +958,7 @@ "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } @@ -892,14 +980,6 @@ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/eslint": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.5.0.tgz", @@ -1013,55 +1093,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/eslint/node_modules/debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", @@ -1104,15 +1135,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/eslint/node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -1128,18 +1150,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/espree": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz", @@ -1154,6 +1164,18 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", @@ -1199,43 +1221,44 @@ "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -1244,6 +1267,17 @@ "node": ">= 0.10.0" } }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1317,11 +1351,30 @@ } }, "node_modules/filelist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", - "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dependencies": { - "minimatch": "^3.0.4" + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, "node_modules/fill-range": { @@ -1337,16 +1390,16 @@ } }, "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "engines": { @@ -1377,6 +1430,38 @@ "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -1388,7 +1473,7 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } @@ -1398,12 +1483,31 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -1470,27 +1574,94 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { - "node": ">=4" + "node": ">=8" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/iconv-lite": { @@ -1548,9 +1719,9 @@ } }, "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ipaddr.js": { "version": "1.9.1", @@ -1565,6 +1736,14 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1613,20 +1792,20 @@ "dev": true }, "node_modules/jake": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", - "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", "dependencies": { - "async": "0.9.x", - "chalk": "^2.4.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" }, "bin": { "jake": "bin/cli.js" }, "engines": { - "node": "*" + "node": ">=10" } }, "node_modules/js-yaml": { @@ -1653,6 +1832,14 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -1706,10 +1893,21 @@ "node": ">=10" } }, + "node_modules/marked": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-6.0.0.tgz", + "integrity": "sha512-7E3m/xIlymrFL5gWswIT4CheIE3fDeh51NV09M4x8iOc7NDYlyERcQMLAIHcSlrvwliwbPQ4OGD+MpPSYiQcqw==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 16" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { "node": ">= 0.6" } @@ -1761,28 +1959,28 @@ } }, "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1793,7 +1991,7 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -1802,17 +2000,25 @@ "dev": true }, "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { "node": ">= 0.6" } }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { "ee-first": "1.1.1" }, @@ -1946,6 +2152,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -1956,11 +2167,17 @@ } }, "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/queue-microtask": { @@ -1992,12 +2209,12 @@ } }, "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -2088,9 +2305,23 @@ } }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/safe-stable-stringify": { "version": "1.1.1", @@ -2102,10 +2333,22 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -2118,51 +2361,51 @@ } }, "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dependencies": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/shebang-command": { "version": "2.0.0", @@ -2185,6 +2428,19 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -2202,6 +2458,11 @@ "node": ">=8" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -2211,11 +2472,11 @@ } }, "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/string_decoder": { @@ -2226,25 +2487,6 @@ "safe-buffer": "~5.2.0" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -2257,6 +2499,14 @@ "node": ">=8" } }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -2270,14 +2520,14 @@ } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/text-hex": { @@ -2304,9 +2554,9 @@ } }, "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "engines": { "node": ">=0.6" } @@ -2390,7 +2640,7 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } @@ -2478,15 +2728,10 @@ "node": ">= 6.4.0" } }, - "node_modules/winston/node_modules/async": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", - "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==" - }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -2497,6 +2742,26 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -2712,6 +2977,15 @@ "@types/node": "*" } }, + "@types/ws": { + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", + "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@typescript-eslint/eslint-plugin": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.7.0.tgz", @@ -2847,12 +3121,12 @@ } }, "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" } }, "acorn": { @@ -2893,11 +3167,26 @@ "dev": true }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" + }, + "dependencies": { + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + } } }, "argparse": { @@ -2918,9 +3207,24 @@ "dev": true }, "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } }, "balanced-match": { "version": "1.0.2", @@ -2928,20 +3232,22 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "requires": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" } }, "brace-expansion": { @@ -2963,9 +3269,18 @@ } }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } }, "callsites": { "version": "3.1.0", @@ -2974,13 +3289,12 @@ "dev": true }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, "color": { @@ -3028,28 +3342,36 @@ "text-hex": "1.0.x" } }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" } }, "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" }, "cookie-signature": { "version": "1.0.6", @@ -3086,15 +3408,20 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, "dir-glob": { "version": "3.0.1", @@ -3130,14 +3457,14 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "ejs": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", - "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", "requires": { - "jake": "^10.6.1" + "jake": "^10.8.5" } }, "enabled": { @@ -3148,7 +3475,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "enquirer": { "version": "2.3.6", @@ -3164,11 +3491,6 @@ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, "eslint": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.5.0.tgz", @@ -3215,40 +3537,6 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", @@ -3274,12 +3562,6 @@ "estraverse": "^5.2.0" } }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -3291,15 +3573,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, @@ -3355,6 +3628,11 @@ "eslint-visitor-keys": "^3.1.0" } }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, "esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", @@ -3388,45 +3666,54 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "requires": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3493,11 +3780,29 @@ } }, "filelist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", - "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "requires": { - "minimatch": "^3.0.4" + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "fill-range": { @@ -3510,16 +3815,16 @@ } }, "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" } }, @@ -3544,6 +3849,21 @@ "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -3552,19 +3872,35 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + } + }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -3610,21 +3946,69 @@ "slash": "^3.0.0" } }, + "gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "requires": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" } }, "iconv-lite": { @@ -3667,9 +4051,9 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ipaddr.js": { "version": "1.9.1", @@ -3681,6 +4065,11 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==" + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3714,14 +4103,14 @@ "dev": true }, "jake": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", - "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", "requires": { - "async": "0.9.x", - "chalk": "^2.4.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" } }, "js-yaml": { @@ -3745,6 +4134,11 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, "kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -3794,10 +4188,15 @@ "yallist": "^4.0.0" } }, + "marked": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-6.0.0.tgz", + "integrity": "sha512-7E3m/xIlymrFL5gWswIT4CheIE3fDeh51NV09M4x8iOc7NDYlyERcQMLAIHcSlrvwliwbPQ4OGD+MpPSYiQcqw==" + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, "merge-descriptors": { "version": "1.0.1", @@ -3831,22 +4230,22 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" } }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } @@ -3854,7 +4253,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "natural-compare": { "version": "1.4.0", @@ -3863,14 +4262,19 @@ "dev": true }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "requires": { "ee-first": "1.1.1" } @@ -3968,6 +4372,11 @@ "ipaddr.js": "1.9.1" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -3975,9 +4384,12 @@ "dev": true }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } }, "queue-microtask": { "version": "1.2.3", @@ -3991,12 +4403,12 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } @@ -4048,9 +4460,9 @@ } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safe-stable-stringify": { "version": "1.1.1", @@ -4062,57 +4474,66 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "requires": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + } + }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "requires": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "dependencies": { "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" } }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "shebang-command": { "version": "2.0.0", @@ -4129,6 +4550,16 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, "simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -4143,15 +4574,20 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, "string_decoder": { "version": "1.3.0", @@ -4159,13 +4595,6 @@ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - } } }, "strip-ansi": { @@ -4177,6 +4606,11 @@ "ansi-regex": "^5.0.1" } }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==" + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4184,11 +4618,11 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } }, "text-hex": { @@ -4212,9 +4646,9 @@ } }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, "triple-beam": { "version": "1.3.0", @@ -4270,7 +4704,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "uri-js": { "version": "4.4.1", @@ -4325,13 +4759,6 @@ "stack-trace": "0.0.x", "triple-beam": "^1.3.0", "winston-transport": "^4.4.0" - }, - "dependencies": { - "async": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", - "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==" - } } }, "winston-transport": { @@ -4345,9 +4772,9 @@ } }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true }, "wrappy": { @@ -4355,6 +4782,12 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "requires": {} + }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index 293868e..d700de3 100644 --- a/package.json +++ b/package.json @@ -14,16 +14,21 @@ "@types/escape-html": "^1.0.1", "@types/express": "^4.17.13", "@types/glob": "^7.2.0", + "axios": "^1.4.0", "dateformat": "^5.0.2", "dotenv-defaults": "^3.0.0", "ejs": "^3.1.6", "escape-html": "^1.0.3", "express": "^4.17.1", "glob": "^7.2.0", - "winston": "^3.3.3" + "gray-matter": "^4.0.3", + "marked": "^6.0.0", + "winston": "^3.3.3", + "ws": "^8.13.0" }, "type": "module", "devDependencies": { + "@types/ws": "^8.5.4", "@typescript-eslint/eslint-plugin": "^5.7.0", "@typescript-eslint/parser": "^5.7.0", "eslint": "^8.5.0" diff --git a/pages/about.wiki b/pages/about.wiki deleted file mode 100644 index 383b1f5..0000000 --- a/pages/about.wiki +++ /dev/null @@ -1,61 +0,0 @@ -__PRIMARY__ -{{NAVBARSORTORDER:2}} -{{DISPLAYTITLE:About}} - -Hello! - -I am a student in the United Kingdom studying computer science at university. -I mainly enjoy building web services and have some interest in cybersecurity, though most of my programming experience is in Java. -Most of my public projects have something to do with ''Minecraft'', as it was through that game where I really got into programming and computer science. - -I also have an interest in physics, specifically astronomy. Had I not chosen to study computer science, I would have likely studied physics instead. - -== Projects == - -Most of my large projects are related to ''Minecraft''. -A lot of other projects aren't listed here simply because they aren't significant enough, and/or because I can't waffle on about them for long enough to fill a whole subsection. - - -=== Quests === - -{{sourcecode|[https://github.com/LMBishop/Quests LMBishop/Quests]}} [[File:questcompass2-256.png|right|150px|Quests logo]] - -Quests enables ''Minecraft'' server owners to create goals or missions for their players to work towards. -It is probably one of my largest projects in terms of both how many people use it and the time I've spent working on it. -As of writing, it is used by approximately 1,200 servers and up to 9,000 players each day. -Unfortunately, I lack the time to properly maintain it, but it is still a project which I am mostly pleased with, as it gave me a good bit of experience designing somewhat large Java projects. - -The main description page can be found on [https://www.spigotmc.org/resources/23696/ SpigotMC]. - -=== Next bus === - -Next bus is a small service which returns live bus data based on open telemetry. -I wrote it as my nearest bus stop lacked a departure board and I knew that bus timings were openly available online. -This was one of my first web projects, and while I admit the the front-end is terrible, it was never designed to look pretty or for anyone but myself to use. -This project helped me to both learn the basics of how the web works (...and to also stop turning up late to lessons). - -While I have no need for it anymore, it is still accessible at [https://leonardobishop.com/~/nextbus/ https://leonardobishop.com/~/nextbus/]. - -=== This webiste === - -{{sourcecode|[https://github.com/LMBishop/website LMBishop/webste]}} -This website was written in TypeScript, and it parses pages written in a markup language and renders it as HTML. -I could've simply written these pages as static HTML, but I hate myself so I decided to over-engineer this solution instead. - -There are some caveats with this system though, in no particular order: -* re-rendering pages are a pain after edits -* files are read from /static/image rather than /pages/file (which breaks the point of the entire namespace system) -* templates can't transclude other templates -* the Template namespace is the only transcludable namespace -* code is a bit wack in places -* I'm never happy with the visual design -* I don't actually know what to fill this website with - -=== u/YTLinkerBot === - -{{sourcecode|[https://github.com/LMBishop/ytlinkerbot LMBishop/ytlinkerbot]}} - -YTLinkerBot is a small reddit bot which automatically crossposts YouTube links to reddit whenever a creator uploads. -This bot was originally written in Java, but it is (mostly) in the process of being re-written with NodeJS. -This is due to the fact that it constantly hits the YouTube Data API quota, as it works by continously polling YouTube for each registered channel. -The new recode will use Google's WebSub service, though the challenge comes with having to automatically manage channel subscriptions for a service which anyone can sign up to, and right now I don't have the time to implement this. diff --git a/pages/blog/steam-deck-workstation.md b/pages/blog/steam-deck-workstation.md new file mode 100644 index 0000000..884282d --- /dev/null +++ b/pages/blog/steam-deck-workstation.md @@ -0,0 +1,99 @@ +--- +title: Steam Deck Workstation +date: !!timestamp '2023-08-03' +--- + +I have this dilemma. Do I: a) spend ages tearing down my PC so I can lug it onto +a train to take to my uni house and rebuild it again there, where it could +get stolen, or b) forego the PC and simply not have a desktop workstation / +gaming rig instead? + +Earlier this year, genius me came up with a third option: +convert my [Steam Deck](https://www.steamdeck.com/en/) +into a desktop PC instead! + +## Why + +While I was back at home over Christmas, I had played and really enjoyed +Overwatch 2, and wanted to keep playing once I went +back to university. Unfortunately for me, my laptop is both not powerful enough, +and not capable of outputting to external displays for Complicated reasons. + +The obvious solution would be to simply bring my PC, however I had a criminally +small desk at the time (which means I have absolutely nowhere to put it, not +even the floor), and it would take too much effort to bring back on the train +with everything else I brought home. + +I remembered I had recently bought a Steam Deck, which had been sitting in +my bag collecting dust, and figured I could try and turn that into my +desktop PC. After all, it *is* a device designed to be portable. + +## Testing Valve's claim + +Valve champions the fact that their Steam Deck can be used as a normal PC. +They have Windows drivers, and even sell a +[dock](https://store.steampowered.com/steamdeckdock), which I bought solely for +this purpose. + +Unfortunately Overwatch breaks when using Proton, which meant I had to install +Windows. This involves the tedious task of partitioning the Steam Deck. +Additionally, my scope had expanded to wanting to install a Linux environment +as well, so I could use it instead of my aforementioned dodgy laptop to work on +projects. + +

      + +
      + GParted running on the Deck. It was as annoying to use as it looks. +
      +
      + +SteamOS is based off Arch, so in theory I could have just installed all +my packages on there and replaced KDE with by preferred sway. However, the root +partition is mounted as read only by default, and any changes made to it get +completely wiped whenever SteamOS is updated. No go. + +Instead, I repartitioned the internal disk and decided to do a triple-boot +setup: SteamOS (so I can still use it as it was intended), Windows (solely to +play Overwatch 2), and Arch (because I use Arch btw). + +
      + +
      + Internal drive partition table +
      +
      + +As the Deck is only 512gb in size, I decided to go with booting Arch +off a microSD card, which would be left inserted in the Deck's built-in microSD +slot. + +## The experience + +For productivity, it was great. I managed to work on some projects using it, +got some university work done, and procrastinated a lot. + +
      + +
      My university setup
      +
      + +For gaming, it was not so great. Turns out running games on a 1080p +monitor is quite a bit more demanding than 720p. Overwatch 2 experienced quite +frequent frame drops, and Counter-Strike was even worse somehow. Not to mention +I was also on Wi-Fi, which means I'm rubber banding all over the joint anyway. + +There were some other issues too. The Steam Deck is nice and fast when a single +game open is in +[gamescope](https://github.com/ValveSoftware/gamescope). +However, when trying to use it as a general desktop PC, +its limitations start becoming much more obvious. Simple things like updating +the system with `pacman` left the system effectively unresponsive until it +completed. Loading a heavy program like IntelliJ also froze up the system until +it finished. I don't know if this is an IO bottleneck (this partition is booted +off a microSD card after all) but I did observe the same 100% CPU utilisation +when doing simple tasks in Windows too. + +## Conclusion + +Maybe just plug a laptop into the monitor next time. diff --git a/pages/contact.html b/pages/contact.html new file mode 100644 index 0000000..bb315a2 --- /dev/null +++ b/pages/contact.html @@ -0,0 +1,59 @@ +--- +stylesheets: + - /css/contact.css +--- +

      Contact

      +
      +
      +
      +

      name

      +
      +
      +

      + Leonardo Bishop +

      +
      +
      +
      +
      +

      pronouns

      +
      +
      +

      + he/him +

      +
      +
      +
      +
      +

      website

      +
      + +
      +
      +
      +

      email

      +
      + +
      +
      +
      +

      github

      +
      +
      + LMBishop +
      +
      +
      +
      +

      subatomic particle

      +
      +
      +

      Neutrino

      +

      +
      +
      diff --git a/pages/contact.wiki b/pages/contact.wiki deleted file mode 100644 index 3ecc059..0000000 --- a/pages/contact.wiki +++ /dev/null @@ -1,16 +0,0 @@ -__PRIMARY__ -{{NAVBARSORTORDER:3}} -{{DISPLAYTITLE:Contact}} - -{{incomplete}} - -You can find me at: -* GitHub: [https://github.com/LMBishop https://github.com/LMBishop] - -You can contact me on: -* Email: contact (at) leonardobishop.com - -== PGP signature == -
      -
      -
      diff --git a/pages/index.html b/pages/index.html new file mode 100644 index 0000000..df4cbae --- /dev/null +++ b/pages/index.html @@ -0,0 +1,42 @@ +--- +stylesheets: + - /css/home.css +--- +
      +
      +
      +
      +

      who

      +
      +
      +

      + Hello I'm Leonardo. I'm currently completing a degree in Computer Science + at university, and I like to spend some of free time working on projects + like Quests, or learning new tools and languages. +

      +

      + You may see me around online using the nick "LMBishop". +

      +
      +
      +
      +
      +

      where

      +
      +
      + +
      +
      +
      +
      +

      what

      +
      +
      +

      + Feel free to look around. This is my personal site where I post about + things which interest me, or share stuff I'm working on. If you're not sure + where to start, check out the now page. +

      +
      +
      +
      diff --git a/pages/index.wiki b/pages/index.wiki deleted file mode 100644 index 64c1415..0000000 --- a/pages/index.wiki +++ /dev/null @@ -1,37 +0,0 @@ -__NOTITLE__ -__PRIMARY__ -{{NAVBARSORTORDER:1}} -{{DISPLAYTITLE:Home}} -
      -β–ˆβ–ˆβ•—     β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•—  β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— 
      -β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—
      -β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•”β–ˆβ–ˆβ–ˆβ–ˆβ•”β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•
      -β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β•šβ•β•β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β• 
      -β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β•šβ•β• β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘     
      -β•šβ•β•β•β•β•β•β•β•šβ•β•     β•šβ•β•β•šβ•β•β•β•β•β• β•šβ•β•β•šβ•β•β•β•β•β•β•β•šβ•β•  β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β•     
      -
      - -Hello! πŸ‘‹ - -I'm '''Leonardo Bishop''', a programmer studying computer science full-time at university. - -You can check out my projects on the [[about]] page. - -== New website == - -This new website is written in TypeScript and these pages are witten in wikitext. - -The source code for this website is available on [https://github.com/LMBishop/website GitHub], freely available under the ISC licence. (If you have suggestions on how to improve it, specifically how the code is designed, please let me know!) - -== Accessing old content == - -All traffic to leonardobishop.com is now redirected to this new website. To access old content on here, you should prepend the path with a tilde (~). - -For example, the following -
      -https://leonardobishop.com/nextbus/
      -
      -will become -
      -https://leonardobishop.com/~/nextbus/
      -
      diff --git a/pages/kpnx.wiki b/pages/kpnx.wiki deleted file mode 100644 index 099a133..0000000 --- a/pages/kpnx.wiki +++ /dev/null @@ -1,98 +0,0 @@ - - diff --git a/pages/now.md b/pages/now.md new file mode 100644 index 0000000..1713514 --- /dev/null +++ b/pages/now.md @@ -0,0 +1,16 @@ +# Now + +Learning Rust. Trying to understand the hype. + +Working on [murder](https://github.com/LMBishop/murder), a port of the classic +gmod game mode by Mechanical Mind for [s&box](https://sbox.facepunch.com/). + +Trying to expand the number of things I can Actually Cook. + +Enjoying the relative freedom and lack of stress during the few weeks I have +after the end of semester, and before my year long placement. + +
      + +*I update this page every so often with what I'm up to. Its contents are +ephemeral, I do not keep a log of them.* diff --git a/pages/spotify.html b/pages/spotify.html new file mode 100644 index 0000000..b0110ba --- /dev/null +++ b/pages/spotify.html @@ -0,0 +1,21 @@ +--- +scripts: + - /scripts/spotify.js +--- +

      Spotify

      + + This is a work in progress once I figure out Spotify's tedious + authentication flow. + +
      + + + +
      + +
      +
      + + This page shows what I'm currently listening to on Spotify. + It requires JavaScript to work. + diff --git a/pages/template/blog.wiki b/pages/template/blog.wiki deleted file mode 100644 index 92b60bd..0000000 --- a/pages/template/blog.wiki +++ /dev/null @@ -1,2 +0,0 @@ -Blog post • {{{date}}}
      -
      diff --git a/pages/template/incomplete.wiki b/pages/template/incomplete.wiki deleted file mode 100644 index 126992f..0000000 --- a/pages/template/incomplete.wiki +++ /dev/null @@ -1 +0,0 @@ -
      πŸ›  This page is a work in progress! Some information may be missing, incomplete, or out of date.
      diff --git a/pages/template/sourcecode.wiki b/pages/template/sourcecode.wiki deleted file mode 100644 index 28ea390..0000000 --- a/pages/template/sourcecode.wiki +++ /dev/null @@ -1 +0,0 @@ -: ''Source code available at {{{1}}}'' diff --git a/pages/test.wiki b/pages/test.wiki deleted file mode 100644 index efb04e8..0000000 --- a/pages/test.wiki +++ /dev/null @@ -1,9 +0,0 @@ -{{NAVBARSORTORDER:4}} -{{DISPLAYTITLE:Test page}} - -This is a test page -* somewhere -* somewhere else - -== Heading == -Content diff --git a/static/css/blog.css b/static/css/blog.css new file mode 100644 index 0000000..2b52dff --- /dev/null +++ b/static/css/blog.css @@ -0,0 +1,63 @@ +#title { + margin: 0 0 3rem 0; +} + +#title > h1 { + margin-bottom: 0.4rem; +} + +figure { + text-align: center; + font-style: italic; + font-size: 0.8rem; +} + +figure img { + max-width: 100%; + border-radius: 10px; +} + +.blog-post, .blog-post-header { + display: flex; + flex-direction: row; + justify-content: space-between; +} + +.blog-post-title { + flex-grow: 1; +} + +.blog-post { + padding: 0.2rem 0; +} + +.blog-post-header { + padding: 0.5rem 0; + color: var(--color-text-muted); +} + +.blog-post-header, .blog-post:last-of-type { + border-bottom: 1px dotted var(--color-text-muted); +} + +#content { + position: relative; +} + +#back-header { + position: relative; + font-size: 1rem; + top: -2rem; + font-family: var(--font-monospace); + width: 700px; +} + +#back-container { + position: absolute; + height: 0; + width: 0; +} + +#back-footer { + margin-top: 4rem; +} diff --git a/static/css/contact.css b/static/css/contact.css new file mode 100644 index 0000000..42bd8d9 --- /dev/null +++ b/static/css/contact.css @@ -0,0 +1,24 @@ +.grid-outer { + width: 100%; + display: flex; + flex-direction: column; + gap: 0; +} + +.grid-inner { + display: flex; + flex-direction: row; + align-items: center; + gap: 1rem; +} + +.grid-title { + flex-basis: 250px; + font-family: var(--font-monospace); + color: var(--color-text-muted); + text-align: right; +} + +.grid-content { + width: 100% +} diff --git a/static/css/globalstyles.css b/static/css/globalstyles.css index 1f22f5e..9fbb974 100644 --- a/static/css/globalstyles.css +++ b/static/css/globalstyles.css @@ -1,113 +1,81 @@ -@import url('https://fonts.googleapis.com/css2?family=Cousine:ital,wght@0,400;0,700;1,400;1,700&display=swap'); - -.website-name { - font-size: 10px; - font-weight: 700; - line-height: 1.2; - color: #ddd; - text-shadow: 0px 1px 10px #9876aa; -} +@import 'variables.css'; html, body { border: 0; margin: 0; background-color: #111; color: #ddd; - font-family: 'Cousine', monospace, sans-serif; - line-height: 1.3; + line-height: 1.6; + font-size: 18px; + font-family: var(--font-sans-serif); } -h1, h2, h3, h4, h5, h6 { - color: #cc7832 -} - -.code-block { - background-color: #222; - border: solid 1px #333; - padding: 10px; -} - -#navbar { - background-color: #222; - width: 100%; +#main-container { display: flex; flex-direction: row; - justify-content: flex-start; - align-items: stretch; - gap: 10px; + width: 100%; + max-height: calc(100vh - 1rem); } -.navbar-element { - background-color: #222; +#navbar { + padding: 2rem 1rem 1rem 6rem; display: flex; - height: 30px; - text-align: center; - line-height: 30px; - padding: 10px; -} - -.navbar-element:hover { - background-color: #888; - transition: 0.2s; - cursor: pointer; + flex-direction: column; + align-items: end; + gap: 0.4rem; + font-size: 0.9em; + font-family: var(--font-monospace); } -.navbar-element > a { - color: #fff; - text-decoration: none; +@media only screen and (max-width: 1000px) { + #navbar { + padding-left: 1rem; + } } -.navbar-element > .highlight { - color: #ffc66d; +a { + color: var(--color-text-link); + text-decoration: underline dotted var(--color-text-link); } -#main-container { - max-width: 1200px; - margin: 0 auto; +a:hover { + background-color: var(--color-text-link-bg); } #content-container { - box-shadow: 0px 0px 15px 10px rgba(152,118,170,0.05); + overflow: scroll; + max-height: 100%; + flex-grow: 1; + scrollbar-color: var(--color-scrollbar) var(--color-background); } -#content { - padding: 20px; - max-width: 1200px; - background-color: #2b2b2b; - margin: 0 auto; +::-webkit-scrollbar { + width: 4px; + background: var(--color-background); } -a { - color: #9876aa; - text-decoration: underline; +::-webkit-scrollbar-thumb { + background: var(--color-scrollbar); + border-radius: 2px; } -.highlight { - color: #ffc66d; +::-webkit-scrollbar-corner { + background: none; } -.footer { - font-size: 10px; -} - -.redlink { - color: #ff4136; +#content { + margin: 8rem auto 6rem auto; + width: 700px; } -.box { - border: solid 1px #fff; - padding: 10px; - background-color: rgba(0, 0, 0, 0.1); +h1, h2, h3, h4 { + font-family: var(--font-monospace); } -.box-red { - border: solid 1px rgba(255, 0, 0, 0.5); - padding: 10px; - background-color: rgba(255, 0, 0, 0.2); +.monospace { + font-family: var(--font-monospace); } -table, th, td { - border: 1px solid rgb(200, 200, 200); - border-collapse: collapse; - padding: 10px; +code { + font-family: var(--font-monospace); } diff --git a/static/css/home.css b/static/css/home.css new file mode 100644 index 0000000..4920ee3 --- /dev/null +++ b/static/css/home.css @@ -0,0 +1,27 @@ +.grid-outer { + width: 100%; + display: flex; + flex-direction: column; + gap: 4rem; +} + +.grid-inner { + display: flex; + flex-direction: row; + gap: 1rem; +} + +.grid-title { + flex-basis: 50px; + font-family: var(--font-monospace); + color: var(--color-text-muted); + text-align: right; +} + +.grid-content { + width: 100% +} + +.spacer { + height: 3rem; +} diff --git a/static/css/variables.css b/static/css/variables.css new file mode 100644 index 0000000..123ee30 --- /dev/null +++ b/static/css/variables.css @@ -0,0 +1,21 @@ +@import url('https://fonts.googleapis.com/css2?family=Chivo:wght@200&family=Hind&family=Noto+Sans&display=swap'); + +@font-face { + font-family: 'Iosevka Web'; + src: url(/fonts/iosevka-medium.woff2) format('woff2'); + font-stretch: condensed; + font-display: swap; +} + +:root { + --font-sans-serif: 'Hind', 'Noto Sans', 'Segoe UI', 'Chivo', sans-serif; + --font-monospace: 'Iosevka Web', monospace; + + --color-background: #111; + --color-text: #ddd; + --color-text-muted: #aaa; + --color-text-link: #ff851b; + --color-text-link-bg: rgba(255, 133, 27, 0.2); + + --color-scrollbar: rgba(255, 255, 255, 0.4); +} diff --git a/static/fonts/iosevka-medium.woff2 b/static/fonts/iosevka-medium.woff2 new file mode 100644 index 0000000..e8d53cd Binary files /dev/null and b/static/fonts/iosevka-medium.woff2 differ diff --git a/static/image/questcompass2-256.png b/static/image/questcompass2-256.png deleted file mode 100644 index 0d0194f..0000000 Binary files a/static/image/questcompass2-256.png and /dev/null differ diff --git a/static/images/steam-deck-arch.jpg b/static/images/steam-deck-arch.jpg new file mode 100644 index 0000000..35dbb42 Binary files /dev/null and b/static/images/steam-deck-arch.jpg differ diff --git a/static/images/steam-deck-gparted.jpg b/static/images/steam-deck-gparted.jpg new file mode 100644 index 0000000..70b72af Binary files /dev/null and b/static/images/steam-deck-gparted.jpg differ diff --git a/static/images/steam-deck-partitions.jpg b/static/images/steam-deck-partitions.jpg new file mode 100644 index 0000000..87d3d9e Binary files /dev/null and b/static/images/steam-deck-partitions.jpg differ diff --git a/static/scripts/purge.js b/static/scripts/purge.js deleted file mode 100644 index 5ee34f0..0000000 --- a/static/scripts/purge.js +++ /dev/null @@ -1,15 +0,0 @@ -$(() => { - $('#confirm').click(() => { - let page = $('#confirm').data('page'); - $.ajax({ - type: 'GET', - url: `/special/purge/${page}/confirm`, - success: () => { - $('#response').html('
      Successfully purged page.
      '); - }, - error: () => { - $('#response').html('
      Could not purge page. Try again later.
      '); - } - }); - }); -}); diff --git a/static/scripts/rebuild.js b/static/scripts/rebuild.js deleted file mode 100644 index 8fd0e2e..0000000 --- a/static/scripts/rebuild.js +++ /dev/null @@ -1,14 +0,0 @@ -$(() => { - $('#confirm').click(() => { - $.ajax({ - type: 'GET', - url: `/special/rebuild/confirm`, - success: () => { - $('#response').html('
      Successfully rebuilt page directory.
      '); - }, - error: () => { - $('#response').html('
      Could not rebuild page directory. Try again later.
      '); - } - }); - }); -}); diff --git a/static/scripts/spotify.js b/static/scripts/spotify.js new file mode 100644 index 0000000..e6551a8 --- /dev/null +++ b/static/scripts/spotify.js @@ -0,0 +1,12 @@ +const connectWebsocket = () => { + document.getElementById('connection-status').innerHTML = "Connecting..."; + let url = new URL(window.location.href); + url.protocol = url.protocol.replace('http', 'ws'); + const socket = new WebSocket(url); + socket.onmessage = (event) => { + const data = JSON.parse(event.data); + console.log(data); + } +} + +document.addEventListener("DOMContentLoaded", connectWebsocket); diff --git a/tsconfig.json b/tsconfig.json index 4477ab2..b37cc35 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "outDir": "./build", "allowJs": true, - "target": "es5", + "target": "es2020", "module": "es2020", "moduleResolution": "node", "allowSyntheticDefaultImports": true, diff --git a/views/blog.ejs b/views/blog.ejs new file mode 100644 index 0000000..238c935 --- /dev/null +++ b/views/blog.ejs @@ -0,0 +1,49 @@ + + + + <%- include('partials/head') %> + + + +
      + <%- include('partials/navbar') %> +
      + <% if (index) { %> +
      +

      Blog

      +
      + title + date +
      + <% for (const blog of blogs) { %> + + + <%= blog.metadata.title %> + + + + <% } %> +
      + <% } else { %> +
      +
      + +
      +
      +

      <%= page.metadata.title %>

      + <%= page.metadata.date?.toDateString() %> +
      + <%- page.html %> + +
      + <% } %> +
      +
      + + diff --git a/views/error.ejs b/views/error.ejs index 88e1a27..838da5b 100644 --- a/views/error.ejs +++ b/views/error.ejs @@ -1,17 +1,15 @@ - Error: <%= code %> + Page not found
      - <%- include('partials/header') %> + <%- include('partials/navbar') %>
      - <%- include('partials/navbar') %>
      -

      An error occurred (<%= code %>)

      -

      Go home?

      +

      Page not found

      diff --git a/views/index.ejs b/views/index.ejs index f47b830..e638ad4 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -1,16 +1,14 @@ - <%= title %> - + <%- include('partials/head') %>
      - <%- include('partials/header') %> + <%- include('partials/navbar') %>
      - <%- include('partials/navbar') %>
      - <%- page %> + <%- content %>
      diff --git a/views/page.ejs b/views/page.ejs deleted file mode 100644 index 2bd4262..0000000 --- a/views/page.ejs +++ /dev/null @@ -1,20 +0,0 @@ - - - - <%= title %> - - - -
      - <%- include('partials/header') %> -
      - <%- include('partials/navbar') %> -
      - <%- content %> -
      - GitHub | View raw | Page built: <%= buildTime %> | Page info -
      -
      -
      - - diff --git a/views/pageinfo.ejs b/views/pageinfo.ejs deleted file mode 100644 index c0ba59d..0000000 --- a/views/pageinfo.ejs +++ /dev/null @@ -1,83 +0,0 @@ - - - - Page information for <%= standardName %> - - - -
      - <%- include('partials/header') %> -
      - <%- include('partials/navbar') %> -
      -

      Information for page <%= standardName %>

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Standard name<%= standardName %>
      Display title<%= displayTitle ?? '-' %>
      Last build<%- (buildTime != 0) ? new Date(buildTime) : '-' %>
      Primary<%= primary ?? false %>
      Show title<%= showTitle ?? false %>
      Sort order<%- sortOrder ?? '-' %>
      Dependencies - <% if (dependencies.size === 0) { %> - <%- '-' %> - <% } else { %> - <% dependencies.forEach(e => { %> - <%- `${e}
      ` %> - <% }); %> - <%}%> -
      Pages which depend on this page - <% if (dependents.size === 0) { %> - <%- '-' %> - <% } else { %> - <% dependents.forEach(e => { %> - <%- `${e}
      ` %> - <% }); %> - <%}%> -
      Errors - <% if (errors.length === 0) { %> - <%- '-' %> - <% } else { %> - <% errors.forEach(e => { %> - <%- `${e.identifier}: ${e.message}
      ` %> - <% }); %> - <%}%> -
      -

      Purge this page?

      -
      - GitHub | View original -
      -
      -
      - - diff --git a/views/partials/head.ejs b/views/partials/head.ejs new file mode 100644 index 0000000..d66fe97 --- /dev/null +++ b/views/partials/head.ejs @@ -0,0 +1,14 @@ +Leonardo Bishop + + +<% if (typeof stylesheets == 'object') { %> + <% for (const sheet of stylesheets) { %> + + <% } %> +<% } %> + +<% if (typeof scripts == 'object') { %> + <% for (const script of scripts) { %> + + <% } %> +<% } %> diff --git a/views/partials/header.ejs b/views/partials/header.ejs deleted file mode 100644 index bd11ce0..0000000 --- a/views/partials/header.ejs +++ /dev/null @@ -1,12 +0,0 @@ -
      -
      -
      -
      diff --git a/views/partials/navbar.ejs b/views/partials/navbar.ejs index ff0c84d..3dbeb6a 100644 --- a/views/partials/navbar.ejs +++ b/views/partials/navbar.ejs @@ -1,3 +1,8 @@ diff --git a/views/purge.ejs b/views/purge.ejs deleted file mode 100644 index df48073..0000000 --- a/views/purge.ejs +++ /dev/null @@ -1,26 +0,0 @@ - - - - Purge page - - - - - -
      - <%- include('partials/header') %> -
      - <%- include('partials/navbar') %> -
      -

      Purge page

      - -

      Are you sure you wish to purge the page <%= page %>?

      -

      The last build time for this page was <%= buildTime %> (<%= buildTimeRelative %> minutes ago).

      - -
      - GitHub | View original -
      -
      -
      - - diff --git a/views/rebuild.ejs b/views/rebuild.ejs deleted file mode 100644 index 9f9cfaa..0000000 --- a/views/rebuild.ejs +++ /dev/null @@ -1,23 +0,0 @@ - - - - Rebuild - - - - - -
      - <%- include('partials/header') %> -
      - <%- include('partials/navbar') %> -
      -

      Rebuild

      - -

      Are you sure you wish to rebuild the page directory?

      - -
      -
      -
      - - -- cgit v1.2.3-70-g09d2