diff --git a/_posts/2020/02/我和你-song.md b/_posts/2020/02/我和你-song.md index 3345f97..ef287f4 100644 --- a/_posts/2020/02/我和你-song.md +++ b/_posts/2020/02/我和你-song.md @@ -6,7 +6,7 @@ tag: - song --- - +<%- youtube('z0tCpDY2Ong') %> diff --git a/_posts/2020/03/zhlevel-level-1.md b/_posts/2020/03/zhlevel-level-1.md index 0d70554..f4f5695 100644 --- a/_posts/2020/03/zhlevel-level-1.md +++ b/_posts/2020/03/zhlevel-level-1.md @@ -7,16 +7,12 @@ tag: Comes from my old repository [here](https://github.com/patarapolw/zhlevel/blob/master/resources/level/hanzi.json). -```pug parsed -a(data-make-html="card" href="https://github.com/patarapolw/zhlevel/blob/master/resources/level/hanzi.json") - | https://github.com/patarapolw/zhlevel/blob/master/resources/level/hanzi.json - pre(data-template style="display: none;"). - image: 'https://avatars3.githubusercontent.com/u/21255931?s=400&v=4' - title: patarapolw/zhlevel - description: >- - Learn Chinese from sentences, Tatoeba, or use your own sentences - - patarapolw/zhlevel - /resources/level/hanzi.json -``` + Level One @@ -51,15 +47,11 @@ Level One According to -```pug parsed -a(data-make-html="card" href="https://github.com/patarapolw/zhlevel/blob/master/resources/level/hsk.yaml") - | https://github.com/patarapolw/zhlevel/blob/master/resources/level/hsk.yaml - pre(data-template style="display: none;"). - image: 'https://avatars3.githubusercontent.com/u/21255931?s=400&v=4' - title: patarapolw/zhlevel - description: >- - Learn Chinese from sentences, Tatoeba, or use your own sentences - - patarapolw/zhlevel - /resources/level/hsk.yaml -``` + 爱, 八, 爸爸, 杯子, 北京, 本, 不, 不客气, 菜, 茶, 吃, 出租车, 打电话, 大, 的, 点, 电脑, 电视, 电影, 东西, 都, 读, 对不起, 多, 多少, 儿子, 二, 饭店, 飞机, 分钟 diff --git a/_posts/2020/04/千里之外-song.md b/_posts/2020/04/千里之外-song.md index 09ec428..a295f91 100644 --- a/_posts/2020/04/千里之外-song.md +++ b/_posts/2020/04/千里之外-song.md @@ -5,7 +5,7 @@ tag: - song --- - +<%- youtube('ocDo3ySyHSI') %> diff --git a/_posts/2020/04/祝福-song.md b/_posts/2020/04/祝福-song.md index d119a2d..4969272 100644 --- a/_posts/2020/04/祝福-song.md +++ b/_posts/2020/04/祝福-song.md @@ -5,7 +5,7 @@ tag: - song --- - +<%- youtube('ZuJM8AOivYU') %> diff --git a/_posts/2020/04/虫儿飞-song.md b/_posts/2020/04/虫儿飞-song.md index f7e987d..9b4466e 100644 --- a/_posts/2020/04/虫儿飞-song.md +++ b/_posts/2020/04/虫儿飞-song.md @@ -5,7 +5,7 @@ tag: - song --- - +<%- youtube('4CazJNOLoM0') %> diff --git a/_posts/千字文/千字文1.1.md b/_posts/千字文/千字文1.1.md index 369b996..e2f86d1 100644 --- a/_posts/千字文/千字文1.1.md +++ b/_posts/千字文/千字文1.1.md @@ -1,41 +1,50 @@ --- title: "千字文 - 1/1" -createdAt: 2019-08-11T00:00:00+07:00 +date: 2019-08-11T00:00:00+07:00 tag: - 千字文 - 汉字 --- -```pug parsed -.w-100.mt-3 - h3.text-center 天地玄黃,宇宙洪荒。 -.w-100 - figure.d-inline-block - img(src="https://upload.wikimedia.org/wikipedia/commons/a/ab/天-order.gif" height=100 data-no-cache) - figcaption.text-center tian1 - figure.d-inline-block - img(src="https://upload.wikimedia.org/wikipedia/commons/f/fb/地-order.gif" height=100 data-no-cache) - figcaption.text-center di4 - figure.d-inline-block - img(src="https://upload.wikimedia.org/wikipedia/commons/d/d3/玄-order.gif" height=100 data-no-cache) - figcaption.text-center xuan2 - figure.d-inline-block - img(src="https://upload.wikimedia.org/wikipedia/commons/e/e7/黄-order.gif" height=100 data-no-cache) - figcaption.text-center huang2 -.w-100 - figure.d-inline-block - img(src="https://www.mdbg.net/chinese/rsc/img/stroke_anim/23431.gif" height=100 data-no-cache) - figcaption.text-center yu3 - figure.d-inline-block - img(src="https://www.mdbg.net/chinese/rsc/img/stroke_anim/23449.gif" height=100 data-no-cache) - figcaption.text-center zhou4 - figure.d-inline-block - img(src="https://www.mdbg.net/chinese/rsc/img/stroke_anim/27946.gif" height=100 data-no-cache) - figcaption.text-center hong2 - figure.d-inline-block - img(src="https://www.mdbg.net/chinese/rsc/img/stroke_anim/33618.gif" height=100 data-no-cache) - figcaption.text-center huang1 -``` +
+

天地玄黃,宇宙洪荒。

+
+
+
+ +
tian1
+
+
+ +
di4
+
+
+ +
xuan2
+
+
+ +
huang2
+
+
+
+
+ +
yu3
+
+
+ +
zhou4
+
+
+ +
hong2
+
+
+ +
huang1
+
+
diff --git a/packages/nuxt/components/PostQuery.vue b/packages/nuxt/components/PostQuery.vue new file mode 100644 index 0000000..56a69e9 --- /dev/null +++ b/packages/nuxt/components/PostQuery.vue @@ -0,0 +1,92 @@ + + + diff --git a/packages/nuxt/components/PostTeaser.vue b/packages/nuxt/components/PostTeaser.vue new file mode 100644 index 0000000..7c940dc --- /dev/null +++ b/packages/nuxt/components/PostTeaser.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/packages/nuxt/components/README.md b/packages/nuxt/components/README.md deleted file mode 100644 index a079f10..0000000 --- a/packages/nuxt/components/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# COMPONENTS - -**This directory is not required, you can delete it if you don't want to use it.** - -The components directory contains your Vue.js Components. - -_Nuxt.js doesn't supercharge these components._ diff --git a/packages/nuxt/layouts/error.vue b/packages/nuxt/layouts/error.vue new file mode 100644 index 0000000..6624ebe --- /dev/null +++ b/packages/nuxt/layouts/error.vue @@ -0,0 +1,15 @@ + + + diff --git a/packages/nuxt/nuxt.config.ts b/packages/nuxt/nuxt.config.ts index 1f6971e..bf8f65e 100644 --- a/packages/nuxt/nuxt.config.ts +++ b/packages/nuxt/nuxt.config.ts @@ -27,13 +27,24 @@ const config = async (): Promise => { : 'https://unpkg.com/awsm.css/dist/awsm.min.css', }, ], + script: [ + { + src: + 'https://unpkg.com/@webcomponents/webcomponentsjs/webcomponents-loader.js', + defer: true, + }, + { + type: 'module', + src: '/webcomponents.js', + }, + ], }, // Global CSS (https://go.nuxtjs.dev/config-css) css: [], // Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins) - plugins: [], + plugins: ['~/plugins/format.ts'], // Auto import components (https://go.nuxtjs.dev/config-components) components: true, @@ -58,6 +69,7 @@ const config = async (): Promise => { env: { THEME: JSON.stringify(theme), }, + serverMiddleware: [{ path: '/api', handler: '~/server/index.ts' }], } } diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 0c157f9..5bfff41 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -35,11 +35,13 @@ "@nuxtjs/eslint-module": "^2.0.0", "@types/better-sqlite3": "^5.4.1", "@types/cheerio": "^0.22.23", + "@types/ejs": "^3.0.5", "@types/fs-extra": "^9.0.5", "@types/rimraf": "^3.0.0", "@types/showdown": "^1.9.3", "babel-eslint": "^10.1.0", "dotenv": "^8.2.0", + "ejs": "^3.1.5", "eslint": "^7.10.0", "eslint-config-prettier": "^6.12.0", "eslint-plugin-nuxt": "^1.0.0", diff --git a/packages/nuxt/pages/_tag.vue b/packages/nuxt/pages/_tag.vue new file mode 100644 index 0000000..bd06e80 --- /dev/null +++ b/packages/nuxt/pages/_tag.vue @@ -0,0 +1,28 @@ + + + diff --git a/packages/nuxt/pages/blog.vue b/packages/nuxt/pages/blog.vue new file mode 100644 index 0000000..eb21903 --- /dev/null +++ b/packages/nuxt/pages/blog.vue @@ -0,0 +1,30 @@ + + + diff --git a/packages/nuxt/pages/index.vue b/packages/nuxt/pages/index.vue index 1b1127a..8de0756 100644 --- a/packages/nuxt/pages/index.vue +++ b/packages/nuxt/pages/index.vue @@ -1,30 +1,9 @@ - - diff --git a/packages/nuxt/plugins/README.md b/packages/nuxt/plugins/README.md deleted file mode 100644 index ca1f9d8..0000000 --- a/packages/nuxt/plugins/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# PLUGINS - -**This directory is not required, you can delete it if you don't want to use it.** - -This directory contains Javascript plugins that you want to run before mounting the root Vue.js application. - -More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins). diff --git a/packages/nuxt/plugins/format.ts b/packages/nuxt/plugins/format.ts new file mode 100644 index 0000000..bf77515 --- /dev/null +++ b/packages/nuxt/plugins/format.ts @@ -0,0 +1,12 @@ +import Vue from 'vue' + +Vue.filter('formatDate', (s: string) => { + return s + ? new Date(s).toLocaleDateString([], { + year: 'numeric', + month: 'long', + day: 'numeric', + weekday: 'short', + }) + : '' +}) diff --git a/packages/nuxt/scripts/dir.ts b/packages/nuxt/scripts/dir.ts index 9cd1f1d..5a4c6d7 100644 --- a/packages/nuxt/scripts/dir.ts +++ b/packages/nuxt/scripts/dir.ts @@ -14,12 +14,6 @@ export const CONTENT_PATH = path.resolve( ) export const srcPath = ( - root: '_post' | '_media' | typeof THEME_FILENAME, + root: '_posts' | '_media' | typeof THEME_FILENAME, ...ps: string[] ): string => path.join(CONTENT_PATH, root, ...ps) - -export const builtPath = (...ps: string[]): string => - path.join(__dirname, '../built', ...ps) - -export const dstMediaPath = (...ps: string[]): string => - path.join(__dirname, '../static/media', ...ps) diff --git a/packages/nuxt/scripts/make-html.ts b/packages/nuxt/scripts/make-html.ts index bc7178f..3efe32e 100644 --- a/packages/nuxt/scripts/make-html.ts +++ b/packages/nuxt/scripts/make-html.ts @@ -2,6 +2,7 @@ import crypto from 'crypto' import scopeCss from '@patarapolw/scope-css' import cheerio from 'cheerio' +import ejs from 'ejs' import jieba from 'nodejieba' import showdown from 'showdown' @@ -16,7 +17,7 @@ export class MakeHTML { strikethrough: true, tables: true, tasklists: true, - simpleLineBreaks: true, + // simpleLineBreaks: true, openLinksInNewWindow: true, backslashEscapesHTMLTags: true, emoji: true, @@ -24,7 +25,7 @@ export class MakeHTML { metadata: true, }) - constructor(private slug: string) { + constructor() { /** * ! For some reasons default underscore italic fails to render... */ @@ -38,18 +39,24 @@ export class MakeHTML { ) } - parse(md: string): string { + async parse( + filename: string + ): Promise<{ + $: cheerio.Cheerio + html(): string + clean(): string + }> { const id = 'md-' + crypto .createHash('sha256') - .update(this.slug || md) + .update(filename) .digest() .toString('hex') .substr(8) const $div = this.$(`
`) - $div.html(this.mdConverter.makeHtml(md)) + $div.html(await this.getHTML(filename)) $div.find('style').each((_, el) => { const $el = this.$(el) const html = $el.html() || '' @@ -58,14 +65,34 @@ export class MakeHTML { } }) - return this.$('
').append($div).html() || '' + return { + $: $div, + html() { + return $div.html() || '' + }, + clean() { + return jieba.cutForSearch($div.text() || '').join(' ') + }, + } } - clean(md: string): string { - const $div = this.$('
') - $div.html(this.mdConverter.makeHtml(md)) - $div.remove('style') - - return jieba.cutForSearch($div.html() || '').join(' ') + private async getHTML(filename: string) { + return this.mdConverter.makeHtml( + await ejs.renderFile(filename, { + youtube: (id: string) => + this.$('
') + .html( + /* html */ ` +
+ +
` + ) + .html(), + }) + ) } } diff --git a/packages/nuxt/scripts/prepare.ts b/packages/nuxt/scripts/prepare.ts index fa1eb36..3594391 100644 --- a/packages/nuxt/scripts/prepare.ts +++ b/packages/nuxt/scripts/prepare.ts @@ -4,8 +4,9 @@ import yaml from 'js-yaml' import rimraf from 'rimraf' import { Database, IMatter } from '../server/db' +import { builtPath, dstMediaPath } from '../server/dir' import { THEME_FILENAME } from '../server/theme' -import { builtPath, dstMediaPath, srcPath } from './dir' +import { srcPath } from './dir' import { MakeHTML } from './make-html' async function main() { @@ -17,40 +18,38 @@ async function main() { await fs.copyFile(srcPath(THEME_FILENAME), builtPath(THEME_FILENAME)) - const db = new Database(builtPath('data.db')) + const db = new Database() db.init() const files = await fg('**/*.md', { - cwd: srcPath('_post'), + cwd: srcPath('_posts'), }) - // eslint-disable-next-line array-callback-return - files.map((f) => { - const path = f.replace(/\.md$/, '') - let markdown = fs.readFileSync(srcPath('_post', f), 'utf8') + const makeHtml = new MakeHTML() - const [h, c = ''] = markdown.substr(4).split(/---\n(.*)$/s) - const header = yaml.safeLoad(h, { - schema: yaml.JSON_SCHEMA, - }) as IMatter - markdown = c + await Promise.all( + files.map(async (f) => { + const path = f.replace(/\.md$/, '') + const markdown = fs.readFileSync(srcPath('_posts', f), 'utf8') - const makeHtml = new MakeHTML(path) + const [h] = markdown.substr(4).split(/---\n(.*)$/s) + const header = yaml.safeLoad(h) as IMatter - const content = makeHtml.clean(markdown) - const excerptHtml = makeHtml.parse( - markdown.split(//)[0] - ) - const contentHtml = makeHtml.parse(markdown) + const r = await makeHtml.parse(srcPath('_posts', f)) + const contentHtml = r.html() + const excerptHtml = contentHtml.split( + // + )[0] - db.insert({ - ...header, - path, - content, - excerptHtml, - contentHtml, + db.insert({ + ...header, + path, + content: r.clean(), + excerptHtml, + contentHtml, + }) }) - }) + ) } if (require.main === module) { diff --git a/packages/nuxt/server/db.ts b/packages/nuxt/server/db.ts index 2310a11..5d1f6b8 100644 --- a/packages/nuxt/server/db.ts +++ b/packages/nuxt/server/db.ts @@ -1,6 +1,8 @@ import sqlite3 from 'better-sqlite3' import * as z from 'zod' +import { builtPath } from './dir' + const zMatter = z.object({ date: z.date().optional(), createdAt: z.date().optional(), @@ -31,8 +33,8 @@ export type IPost = z.infer export class Database { db: sqlite3.Database - constructor(public filepath: string, opts?: sqlite3.Options) { - this.db = sqlite3(filepath, opts) + constructor(opts?: sqlite3.Options) { + this.db = sqlite3(builtPath('data.db'), opts) } public init(): void { @@ -40,8 +42,8 @@ export class Database { CREATE TABLE IF NOT EXISTS files ( [path] TEXT PRIMARY KEY, [date] INT, -- epoch milli - [createdAt] INT, -- epoch milli - [updatedAt] INT, -- epoch milli + createdAt INT, -- epoch milli + updatedAt INT, -- epoch milli priority INT, -- q.title [image] TEXT, @@ -83,20 +85,158 @@ export class Database { this.db.transaction(() => { // eslint-disable-next-line array-callback-return ps.map((p) => { - p = zPost.parse(p) + const { + path, + date, + createdAt, + updatedAt, + priority, + image, + excerptHtml, + contentHtml, + title, + tag, + category, + content, + } = zPost.parse(p) fStmt.run({ - ...p, - date: p.date ? p.date.getTime() : undefined, - createdAt: p.createdAt ? p.createdAt.getTime() : undefined, - updatedAt: p.updatedAt ? p.updatedAt.getTime() : undefined, + path, + priority, + image, + excerptHtml, + contentHtml, + date: date ? date.getTime() : null, + createdAt: createdAt ? createdAt.getTime() : null, + updatedAt: updatedAt ? updatedAt.getTime() : null, }) qStmt.run({ - ...p, - tag: p.tag ? p.tag.join(' ') : undefined, + path, + title, + category, + content, + tag: tag ? tag.join(' ') : undefined, }) }) })() } + + public get(id: string) { + const r = this.db + .prepare( + /* sql */ ` + SELECT + [date], + title, + [image], + tag, + category, + excerptHtml excerpt, + contentHtml content + FROM files f + JOIN q ON q.path = f.path + WHERE f.path = @id + ` + ) + .get({ id }) + + if (!r) { + return null + } + + return { + ...r, + date: r.date ? new Date(r.date) : undefined, + tag: r.tag ? r.tag.split(/ /g) : undefined, + } as { + date?: Date + title: string + image?: string + tag?: string[] + category?: string + excerpt: string + content: string + } + } + + public q( + q: string, + opts: { + offset: number + limit: number + } + ) { + return this._search(q, opts, 'RANK') + } + + public by( + q: string, + opts: { + offset: number + limit: number + } + ) { + return this._search( + q, + opts, + 'priority DESC, [date] DESC, createdAt DESC, updatedAt DESC' + ) + } + + private _search( + q: string, + opts: { + offset: number + limit: number + }, + orderedBy: string + ) { + const fromSegment = /* sql */ ` + FROM files f + JOIN q ON q.path = f.path + ${q ? `WHERE q = @q` : ''} + ` + + const count = + this.db + .prepare( + /* sql */ ` + SELECT COUNT(f.path) [count] + ${fromSegment} + ` + ) + .get({ q })?.count || 0 + + const result = this.db + .prepare( + /* sql */ ` + SELECT + f.path [path], + [date], + title, + [image], + tag, + category, + excerptHtml excerpt + ${fromSegment} + ORDER BY ${orderedBy} + LIMIT ${opts.limit} OFFSET ${opts.offset} + ` + ) + .all({ q }) as { + path: string + date?: Date + title: string + image?: string + tag?: string[] + category?: string + excerpt: string + }[] + + return { + result, + count, + } + } } diff --git a/packages/nuxt/server/dir.ts b/packages/nuxt/server/dir.ts new file mode 100644 index 0000000..d3f51cb --- /dev/null +++ b/packages/nuxt/server/dir.ts @@ -0,0 +1,7 @@ +import path from 'path' + +export const builtPath = (...ps: string[]): string => + path.join(__dirname, '../built', ...ps) + +export const dstMediaPath = (...ps: string[]): string => + path.join(__dirname, '../static/media', ...ps) diff --git a/packages/nuxt/server/index.ts b/packages/nuxt/server/index.ts new file mode 100644 index 0000000..9b1dc03 --- /dev/null +++ b/packages/nuxt/server/index.ts @@ -0,0 +1,58 @@ +import express from 'express' +import * as z from 'zod' + +import { Database } from './db' + +const app = express() +const db = new Database({ readonly: true }) + +app.get('/', (req, res) => { + const { id } = z + .object({ + id: z.string(), + }) + .parse(req.query) + + const r = db.get(id) + if (!r) { + res.sendStatus(404) + return + } + + res.json(r) +}) + +app.get('/q', (req, res) => { + const { q, tag, page: _page = '1' } = z + .object({ + q: z.string().optional(), + tag: z.string().optional(), + page: z + .string() + .refine((s) => /^\d+$/.test(s)) + .optional(), + }) + .parse(req.query) + + const perPage = 5 + const offset = (parseInt(_page) - 1) * perPage + + if (q) { + res.json( + db.q(`${q} ${tag ? `tag:${tag}` : ''}`, { + offset, + limit: perPage, + }) + ) + return + } + + res.json( + db.by(tag ? `tag:${tag}` : '', { + offset, + limit: perPage, + }) + ) +}) + +export default app diff --git a/packages/nuxt/static/webcomponents.js b/packages/nuxt/static/webcomponents.js new file mode 100644 index 0000000..1e95c92 --- /dev/null +++ b/packages/nuxt/static/webcomponents.js @@ -0,0 +1,11 @@ +/* global WebComponents */ +WebComponents.waitFor(() => { + // At this point we are guaranteed that all required polyfills have + // loaded, and can use web components API's. + // The standard pattern is to load element definitions that call + // `customElements.define` here. + // Note: returning the import's promise causes the custom elements + // polyfill to wait until all definitions are loaded and then upgrade + // the document in one batch, for better performance. + return import('https://unpkg.com/@patarapolw/make-html-x-card') +}) diff --git a/packages/nuxt/tsconfig.json b/packages/nuxt/tsconfig.json index 65f9bbc..1270666 100644 --- a/packages/nuxt/tsconfig.json +++ b/packages/nuxt/tsconfig.json @@ -3,11 +3,7 @@ "target": "ES2018", "module": "ESNext", "moduleResolution": "Node", - "lib": [ - "ESNext", - "ESNext.AsyncIterable", - "DOM" - ], + "lib": ["ESNext", "ESNext.AsyncIterable", "DOM"], "esModuleInterop": true, "allowJs": true, "sourceMap": true, @@ -16,21 +12,10 @@ "experimentalDecorators": true, "baseUrl": ".", "paths": { - "~/*": [ - "./*" - ], - "@/*": [ - "./*" - ] + "~/*": ["./*"], + "@/*": ["./*"] }, - "types": [ - "@types/node", - "@nuxt/types" - ] + "types": ["@types/node", "@nuxt/types", "@nuxtjs/axios"] }, - "exclude": [ - "node_modules", - ".nuxt", - "dist" - ] + "exclude": ["node_modules", ".nuxt", "dist"] } diff --git a/packages/nuxt/yarn.lock b/packages/nuxt/yarn.lock index 4a82cd4..f80aa68 100644 --- a/packages/nuxt/yarn.lock +++ b/packages/nuxt/yarn.lock @@ -1404,6 +1404,11 @@ dependencies: "@types/node" "*" +"@types/ejs@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/ejs/-/ejs-3.0.5.tgz#95a3a1c3d9603eba80fe67ff56da1ba275ef2eda" + integrity sha512-k4ef69sS4sIqAPW9GoBnN+URAON2LeL1H0duQvL4RgdEBna19/WattYSA1qYqvbVEDRTSWzOw56tCLhC/m/IOw== + "@types/eslint-visitor-keys@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" @@ -2273,6 +2278,11 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== +async@0.9.x: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= + at-least-node@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" @@ -3749,6 +3759,13 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== +ejs@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.5.tgz#aed723844dc20acb4b170cd9ab1017e476a0d93b" + integrity sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w== + dependencies: + jake "^10.6.1" + electron-to-chromium@^1.3.621: version "1.3.626" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.626.tgz#48acdf322be07feb2c1330ba05e4bf6327f721a3" @@ -4417,6 +4434,13 @@ file-uri-to-path@1.0.0: resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== +filelist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.1.tgz#f10d1a3ae86c1694808e8f20906f43d4c9132dbb" + integrity sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ== + dependencies: + minimatch "^3.0.4" + filesize@^3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" @@ -5528,6 +5552,16 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= +jake@^10.6.1: + version "10.8.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b" + integrity sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A== + dependencies: + async "0.9.x" + chalk "^2.4.2" + filelist "^1.0.1" + minimatch "^3.0.4" + jest-worker@^25.4.0: version "25.5.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.5.0.tgz#2611d071b79cea0f43ee57a3d118593ac1547db1"