From ffa193b5dd54a034778b84300eb2f3ee5ad605a9 Mon Sep 17 00:00:00 2001 From: masnn Date: Fri, 3 Apr 2020 22:37:30 +0800 Subject: [PATCH] template: problem_detail --- hydro/development.js | 8 ++- hydro/handler/base.js | 14 ++-- hydro/handler/judge.js | 12 ++-- hydro/handler/problem.js | 1 + hydro/handler/ui.js | 56 +++++++++++++--- hydro/handler/user.js | 24 ++++--- hydro/lib/i18n.js | 4 +- hydro/service/server.js | 33 --------- package.json | 4 ++ templates/components/comments_solution.html | 2 +- templates/components/problem.html | 4 +- templates/components/user.html | 2 +- templates/contest_main.html | 2 +- templates/discussion_detail.html | 22 +++--- templates/discussion_edit.html | 2 +- templates/discussion_main_or_node.html | 2 +- templates/domain_base.html | 4 +- templates/domain_main.html | 2 +- templates/domain_manage_permission.html | 2 +- templates/error.html | 1 + templates/homework_main.html | 2 +- templates/layout/html5.html | 4 +- templates/partials/contest_sidebar.html | 8 +-- templates/partials/discussion_edit_form.html | 2 +- templates/partials/homework_sidebar.html | 6 +- templates/partials/login_dialog.html | 8 +-- templates/partials/nav.html | 54 ++++++--------- templates/partials/problem_sidebar.html | 12 ++-- .../partials/problem_sidebar_contest.html | 4 +- .../partials/problem_sidebar_homework.html | 4 +- .../partials/problem_sidebar_normal.html | 16 ++--- templates/problem_detail.html | 67 ++++--------------- templates/problem_main.html | 15 ++--- templates/problem_settings.html | 2 +- templates/problem_solution.html | 20 +++--- templates/record_detail.html | 4 +- templates/record_main_tr.html | 4 +- templates/training_detail.html | 2 +- templates/training_main.html | 2 +- templates/user_detail.html | 4 +- templates/user_login.html | 2 +- templates/wiki_help.html | 2 +- yarn.lock | 62 +++++++++++++++++ 43 files changed, 265 insertions(+), 242 deletions(-) diff --git a/hydro/development.js b/hydro/development.js index 743e7da1..c27e6c99 100644 --- a/hydro/development.js +++ b/hydro/development.js @@ -16,6 +16,11 @@ process.on('restart', async () => { delete require.cache; run(); }); +const path = require('path'); +const i18n = require('./lib/i18n'); +i18n(path.resolve(__dirname, '..', 'locales', 'zh_CN.yaml'), 'zh_CN'); + + const EventEmitter = require('events'); global.bus = new EventEmitter(); async function run() { @@ -27,13 +32,14 @@ async function run() { }); }); let server = require('./service/server'); - require('./lib/i18n'); + require('./handler/ui'); require('./handler/base'); require('./handler/home'); require('./handler/problem'); require('./handler/record'); require('./handler/judge'); + require('./handler/user'); server.start(); } run().catch(e => { diff --git a/hydro/handler/base.js b/hydro/handler/base.js index e0d9673b..d36a2d60 100644 --- a/hydro/handler/base.js +++ b/hydro/handler/base.js @@ -15,13 +15,9 @@ MIDDLEWARE(async (ctx, next) => { let sid = ctx.cookies.get('sid'); let save = ctx.cookies.get('save'); let tokenType, expireSeconds; - if (save) { - tokenType = token.TYPE_SAVED_SESSION; - expireSeconds = options.session.saved_expire_seconds; - } else { - tokenType = token.TYPE_UNSAVED_SESSION; - expireSeconds = options.session.unsaved_expire_seconds; - } + tokenType = token.TYPE_SESSION; + if (save) expireSeconds = options.session.saved_expire_seconds; + else expireSeconds = options.session.unsaved_expire_seconds; ctx.session = sid ? await token.update(sid, tokenType, expireSeconds, Object.assign({ update_ip: ctx.request.ip, @@ -48,6 +44,7 @@ MIDDLEWARE(async (ctx, next) => { } } }; + console.log(ctx.session.uid); await next(); if (ctx.session.sid) await token.update(ctx.session.sid, tokenType, expireSeconds, Object.assign({ @@ -61,7 +58,8 @@ MIDDLEWARE(async (ctx, next) => { update_ip: ctx.request.ip, update_ua: ctx.request.headers['user-agent'] || '' }, ctx.session)); - let cookie = { domain: options.session.domain, secure: options.session.secure, httponly: true }; + console.log(ctx.session.sid, ctx.session.uid); + let cookie = { secure: options.session.secure, httponly: true }; if (save) { cookie.expires = ctx.session.expireAt, cookie.maxAge = expireSeconds; ctx.cookies.set('save', 'true', cookie); diff --git a/hydro/handler/judge.js b/hydro/handler/judge.js index d535e2a9..8c172b44 100644 --- a/hydro/handler/judge.js +++ b/hydro/handler/judge.js @@ -1,5 +1,5 @@ const - { CONTEXT } = require('../service/server'), + { GET, POST } = require('../service/server'), queue = require('../service/queue'), record = require('../model/record'), { requirePerm } = require('./tools'), @@ -7,12 +7,10 @@ const queue.assert('judge'); -const { MIDDLEWARE, GET, POST } = CONTEXT(); -MIDDLEWARE(requirePerm(PERM_JUDGE)); -GET('/judge/noop', async ctx => { +GET('/judge/noop', requirePerm(PERM_JUDGE), async ctx => { ctx.body = {}; }); -GET('/judge/fetch', async ctx => { +GET('/judge/fetch', requirePerm(PERM_JUDGE), async ctx => { let rid = await queue.get('judge', false); if (rid) { let rdoc = await record.get(rid); @@ -27,9 +25,9 @@ GET('/judge/fetch', async ctx => { ctx.body = data; } }); -POST('/judge/next', async ctx => { +POST('/judge/next', requirePerm(PERM_JUDGE), async ctx => { console.log(ctx.request.body); }); -POST('/judge/end', async ctx => { +POST('/judge/end', requirePerm(PERM_JUDGE), async ctx => { console.log(ctx.request.body); }); diff --git a/hydro/handler/problem.js b/hydro/handler/problem.js index b3fa21d0..56803a99 100644 --- a/hydro/handler/problem.js +++ b/hydro/handler/problem.js @@ -38,6 +38,7 @@ GET('/p/:pid', requirePerm(PERM_VIEW_PROBLEM), async ctx => { let pdoc = await problem.get({ pid, uid }); if (pdoc.hidden) ctx.checkPerm(PERM_VIEW_PROBLEM_HIDDEN); let udoc = await user.getById(pdoc.owner); + ctx.templateName = 'problem_detail.html'; ctx.body = { pdoc, udoc, title: pdoc.title }; }); POST('/p/:pid/submit', requirePerm(PERM_SUBMIT_PROBLEM), async ctx => { diff --git a/hydro/handler/ui.js b/hydro/handler/ui.js index fc2137a4..7858a78b 100644 --- a/hydro/handler/ui.js +++ b/hydro/handler/ui.js @@ -1,25 +1,58 @@ const path = require('path'), + md5 = require('blueimp-md5'), static = require('koa-static'), nunjucks = require('nunjucks'), + hljs = require('hljs'), + MarkdownIt = require('markdown-it'), + katex = require('markdown-it-katex'), options = require('../options'), perm = require('../permission'), builtin = require('../model/builtin'), { MIDDLEWARE } = require('../service/server'), - { NotFoundError } = require('../error'); + { NotFoundError } = require('../error'), + MD5_REGEX = /^[0-9a-f]{32}$/; +function getHash(email) { + email = (typeof email === 'string') ? email.trim().toLowerCase() : 'unspecified'; + return email.match(MD5_REGEX) ? email : md5(email); +} + +class Markdown extends MarkdownIt { + constructor() { + super({ + linkify: true, + highlight: function (str, lang) { + if (lang && hljs.getLanguage(lang)) + try { + return hljs.highlight(lang, str).value; + } catch (__) { } // eslint-disable-line no-empty + return ''; + } + }); + this.linkify.tlds('.py', false); + this.use(katex); + } +} +const md = new Markdown(); class Nunjucks extends nunjucks.Environment { constructor() { super( new nunjucks.FileSystemLoader(path.resolve(options.template.path)), { autoescape: true, trimBlocks: true } ); - this.addFilter('json', function (data) { - return JSON.stringify(data); + this.addFilter('json', function (self) { + return JSON.stringify(self); }, false); this.addFilter('assign', function (self, data) { return Object.assign(self, data); }); + this.addFilter('markdown', function (self) { + return md.render(self); + }); + this.addFilter('gravatar_url', function (email, size) { + return `//gravatar.loli.net/avatar/${getHash(email)}?d=mm&s=${size}`; + }); this.addGlobal('static_url', str => `/${str}`); this.addGlobal('reverse_url', str => str); this.addGlobal('perm', perm); @@ -30,8 +63,10 @@ const env = new Nunjucks(); MIDDLEWARE(static(path.resolve(process.cwd(), '.uibuild'))); MIDDLEWARE(async (ctx, next) => { ctx.render_title = str => str; - ctx.ui_context = {}; - ctx.user_context = {}; + ctx.UIContext = { + cdn_prefix: '/', + url_prefix: '/' + }; ctx.render = async (name, context) => { ctx.user = ctx.state.user; ctx.translate = str => { @@ -53,12 +88,17 @@ MIDDLEWARE(async (ctx, next) => { try { await next(); if (!ctx.body) throw new NotFoundError(); + if (ctx.query.template || ctx.templateName) { + Object.assign(ctx.body, JSON.parse(ctx.query.data || '{}')); + await ctx.render(ctx.query.template || ctx.templateName, ctx.body); + } else if (ctx.setRedirect) { + ctx.response.type = 'application/octet-stream'; + ctx.redirect(ctx.setRedirect); + } } catch (error) { + if (error.toString().startsWith('Template render error')) throw error; await ctx.render('error.html', { error }); } - Object.assign(ctx.body, JSON.parse(ctx.query.data || '{}')); - console.log(ctx.body); - if (ctx.query.template || ctx.templateName) await ctx.render(ctx.query.template || ctx.templateName, ctx.body); } catch (error) { await ctx.render('bsod.html', { error }); } diff --git a/hydro/handler/user.js b/hydro/handler/user.js index a653e274..7405dedf 100644 --- a/hydro/handler/user.js +++ b/hydro/handler/user.js @@ -12,12 +12,16 @@ const GET('/user', async ctx => { let udoc = await user.getById(ctx.session.uid); + ctx.templateName = 'user_detail.html'; ctx.body = { udoc }; }); +GET('/login', async ctx => { + ctx.templateName = 'user_login.html'; +}); POST('/login', async ctx => { - let { username, password, rememberme } = ctx.request.body; - let udoc = await user.getByUname(username); - if (!udoc) throw new LoginError(username); + let { uname, password, rememberme = false } = ctx.request.body; + let udoc = await user.getByUname(uname); + if (!udoc) throw new LoginError(uname); if (udoc) udoc.checkPassword(password); await user.setById(udoc._id, { loginat: new Date(), loginip: ctx.request.ip }); udoc.salt = ''; @@ -25,22 +29,20 @@ POST('/login', async ctx => { console.log(udoc); ctx.session.uid = udoc._id; ctx.session.rememberme = rememberme; - ctx.body = { udoc }; + ctx.body = {}; + ctx.setRedirect = ctx.request.headers.referer || '/'; }); POST('/logout', requirePerm(PERM_LOGGEDIN), async ctx => { ctx.session = { uid: 1 }; ctx.body = {}; }); -let { GET: _GET, POST: _POST, MIDDLEWARE: _MIDDLEWARE } = CONTEXT(); -_MIDDLEWARE(requirePerm(PERM_REGISTER_USER)); - -_GET('/register/:code', async ctx => { +GET('/register/:code', requirePerm(PERM_REGISTER_USER), async ctx => { let code = ctx.request.body.code; let { mail } = await token.get(code, token.TYPE_REGISTRATION); if (!mail) throw new InvalidTokenError(token.TYPE_REGISTRATION, code); ctx.body = { mail }; }); -_GET('/register/:code', async ctx => { +GET('/register/:code', requirePerm(PERM_REGISTER_USER), async ctx => { let { code, password, verify_password, uname } = ctx.request.body; let { mail } = await token.get(code, token.TYPE_REGISTRATION); if (!mail) throw new InvalidTokenError(token.TYPE_REGISTRATION, code); @@ -53,7 +55,7 @@ _GET('/register/:code', async ctx => { }); if (options.smtp.user) { - _POST('/register', limitRate('send_mail', 3600, 30), async ctx => { + POST('/register', requirePerm(PERM_REGISTER_USER), limitRate('send_mail', 3600, 30), async ctx => { let email = ctx.request.body.email; validator.check_mail(email); if (await user.get_by_mail(email)) throw new UserAlreadyExistError(email); @@ -95,7 +97,7 @@ if (options.smtp.user) { ctx.redirect('/'); }); } else - _POST('/register', async ctx => { + POST('/register', requirePerm(PERM_REGISTER_USER), async ctx => { let email = ctx.request.body.email; validator.check_mail(email); if (await user.get_by_mail(email)) throw new UserAlreadyExistError(email); diff --git a/hydro/lib/i18n.js b/hydro/lib/i18n.js index 28f46159..495b20d3 100644 --- a/hydro/lib/i18n.js +++ b/hydro/lib/i18n.js @@ -25,8 +25,8 @@ String.prototype.rawformat = function (object) { let res = this.split('{@}'); return [res[0], object, res[1]]; }; -String.prototype.translate = function (language = 'zh-CN') { - if (locales[language]) return this; +String.prototype.translate = function (language = 'zh_CN') { + if (locales[language]) return locales[language][this] || this; else return this; }; diff --git a/hydro/service/server.js b/hydro/service/server.js index 0e137dbb..0b59fafc 100644 --- a/hydro/service/server.js +++ b/hydro/service/server.js @@ -13,37 +13,7 @@ let server = http.createServer(app.callback()); app.keys = options.session.keys; app.use(morgan(':method :url :status :res[content-length] - :response-time ms')); app.use(Body()); - let router = new Router(); -let contexts = []; -function CONTEXT() { - this.router = new Router(); - /** - * @param {import('koa').Middleware} middleware - */ - function MIDDLEWARE(middleware) { - router.use(middleware); - } - /** - * @param {string} route - * @param {...import('koa').Middleware} handler - */ - function GET(route, ...handler) { - router.get(route, ...handler); - } - /** - * @param {string} route - * @param {...import('koa').Middleware} handler - */ - function POST(route, ...handler) { - router.post(route, ...handler); - } - this.MIDDLEWARE = MIDDLEWARE; - this.GET = GET; - this.POST = POST; - contexts.push(this); - return this; -} /** * @param {import('koa').Middleware} middleware @@ -78,15 +48,12 @@ function SOCKET(prefix, handler) { sock.on('connection', handler); sock.installHandlers(server); } -exports.CONTEXT = CONTEXT; exports.MIDDLEWARE = MIDDLEWARE; exports.GET = GET; exports.POST = POST; exports.SOCKET = SOCKET; exports.start = function start() { app.use(router.routes()).use(router.allowedMethods()); - for (let c of contexts) - app.use(c.router.routes()).use(c.router.allowedMethods()); app.listen(options.listen.port); console.log('Server listening at: %s', options.listen.port); }; diff --git a/package.json b/package.json index aa708227..4734db4b 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,9 @@ "license": "MIT", "dependencies": { "axios": "^0.19.0", + "blueimp-md5": "^2.13.0", "bson": "^4.0.2", + "hljs": "^6.2.3", "js-yaml": "^3.13.1", "koa": "^2.11.0", "koa-body": "^4.1.1", @@ -15,6 +17,8 @@ "koa-router": "^7.4.0", "koa-static": "^5.0.0", "lodash": "^4.17.15", + "markdown-it": "^10.0.0", + "markdown-it-katex": "^2.0.3", "mongodb": "^3.3.4", "nodemailer": "^6.3.1", "nunjucks": "^3.2.1", diff --git a/templates/components/comments_solution.html b/templates/components/comments_solution.html index a9af76c4..9ad99982 100644 --- a/templates/components/comments_solution.html +++ b/templates/components/comments_solution.html @@ -34,7 +34,7 @@
{% if not mode_create %}
- {% if handler.has_perm(vj4.model.builtin.PERM_VOTE_PROBLEM_SOLUTION) %} + {% if handler.has_perm(perm.PERM_VOTE_PROBLEM_SOLUTION) %}
{{ doc['vote'] }}
diff --git a/templates/components/problem.html b/templates/components/problem.html index 94a83fd5..3f9c1799 100644 --- a/templates/components/problem.html +++ b/templates/components/problem.html @@ -2,7 +2,7 @@ {%- if not invalid %} 0 %} {%- else %} diff --git a/templates/components/user.html b/templates/components/user.html index 588685ce..a1e5501d 100644 --- a/templates/components/user.html +++ b/templates/components/user.html @@ -18,7 +18,7 @@ {% if badge %} -{% if modbadge and handler.dudoc_has_perm(udoc, dudoc, vj4.model.builtin.PERM_MOD_BADGE) %} +{% if modbadge and handler.dudoc_has_perm(udoc, dudoc, perm.PERM_MOD_BADGE) %} {% endif %} {% endif %} diff --git a/templates/contest_main.html b/templates/contest_main.html index ac93c5e4..fe1a1230 100644 --- a/templates/contest_main.html +++ b/templates/contest_main.html @@ -115,7 +115,7 @@
- {% if handler.has_perm(vj4.model.builtin.PERM_CREATE_CONTEST) %} + {% if handler.has_perm(perm.PERM_CREATE_CONTEST) %}

diff --git a/templates/discussion_detail.html b/templates/discussion_detail.html index 580a4197..868c694d 100644 --- a/templates/discussion_detail.html +++ b/templates/discussion_detail.html @@ -29,7 +29,7 @@

{% if vnode %} - {% if handler.has_perm(vj4.model.builtin.PERM_CREATE_DISCUSSION) %} + {% if handler.has_perm(perm.PERM_CREATE_DISCUSSION) %}

{{ _('Create a Discussion') }}

{% else %} {% if not handler.has_perm(perm.PERM_LOGGEDIN) %} diff --git a/templates/domain_base.html b/templates/domain_base.html index bd061837..b3a4d183 100644 --- a/templates/domain_base.html +++ b/templates/domain_base.html @@ -13,7 +13,7 @@
- {% if handler.has_perm(vj4.model.builtin.PERM_EDIT_PERM) %} + {% if handler.has_perm(perm.PERM_EDIT_PERM) %}
  • - {{ category }} + {{ category }}

    {% if sub_categories | length > 0 %}
      {% for sub_category in sub_categories %}
    1. - {{ sub_category }} + {{ sub_category }}
    2. {% endfor %}
    @@ -52,9 +52,8 @@

    {{ _('Search') }}

    -
    +
    - @@ -62,21 +61,21 @@
  • - {% if handler.has_perm(vj4.model.builtin.PERM_CREATE_PROBLEM) %} + {% if handler.has_perm(perm.PERM_CREATE_PROBLEM) %}

    {{ _('Create Problem') }}

    diff --git a/templates/problem_settings.html b/templates/problem_settings.html index 959c0d21..cdd1919a 100644 --- a/templates/problem_settings.html +++ b/templates/problem_settings.html @@ -9,7 +9,7 @@

    {{ _('Hint') }}: {{ _('Dataset Format') }}, {{ _('An example of dataset') }}: {{ _('Download') }}

    - {% if pdoc and (handler.own(pdoc, vj4.model.builtin.PERM_READ_PROBLEM_DATA_SELF) or handler.has_perm(vj4.model.builtin.PERM_READ_PROBLEM_DATA) or handler.has_priv(vj4.model.builtin.PRIV_READ_PROBLEM_DATA)) %} + {% if pdoc and (handler.own(pdoc, perm.PERM_READ_PROBLEM_DATA_SELF) or handler.has_perm(perm.PERM_READ_PROBLEM_DATA) or handler.has_priv(vj4.model.builtin.PRIV_READ_PROBLEM_DATA)) %}

    {{ _('Download Dataset') }}

    {% endif %}
    diff --git a/templates/problem_solution.html b/templates/problem_solution.html index 3c775505..3c4aac9a 100644 --- a/templates/problem_solution.html +++ b/templates/problem_solution.html @@ -22,16 +22,16 @@ reply_edit_op = 'edit_reply', comment_delete_op = 'delete_solution', reply_delete_op = 'delete_reply', - comment_post_perm = vj4.model.builtin.PERM_CREATE_PROBLEM_SOLUTION, - comment_edit_perm = vj4.model.builtin.PERM_EDIT_PROBLEM_SOLUTION, - comment_edit_self_perm = vj4.model.builtin.PERM_EDIT_PROBLEM_SOLUTION_SELF, - comment_delete_perm = vj4.model.builtin.PERM_DELETE_PROBLEM_SOLUTION, - comment_delete_self_perm = vj4.model.builtin.PERM_DELETE_PROBLEM_SOLUTION_SELF, - reply_post_perm = vj4.model.builtin.PERM_REPLY_PROBLEM_SOLUTION, - reply_edit_perm = vj4.model.builtin.PERM_EDIT_PROBLEM_SOLUTION_REPLY, - reply_edit_self_perm = vj4.model.builtin.PERM_EDIT_PROBLEM_SOLUTION_REPLY_SELF, - reply_delete_perm = vj4.model.builtin.PERM_DELETE_PROBLEM_SOLUTION_REPLY, - reply_delete_self_perm = vj4.model.builtin.PERM_DELETE_PROBLEM_SOLUTION_REPLY_SELF + comment_post_perm = perm.PERM_CREATE_PROBLEM_SOLUTION, + comment_edit_perm = perm.PERM_EDIT_PROBLEM_SOLUTION, + comment_edit_self_perm = perm.PERM_EDIT_PROBLEM_SOLUTION_SELF, + comment_delete_perm = perm.PERM_DELETE_PROBLEM_SOLUTION, + comment_delete_self_perm = perm.PERM_DELETE_PROBLEM_SOLUTION_SELF, + reply_post_perm = perm.PERM_REPLY_PROBLEM_SOLUTION, + reply_edit_perm = perm.PERM_EDIT_PROBLEM_SOLUTION_REPLY, + reply_edit_self_perm = perm.PERM_EDIT_PROBLEM_SOLUTION_REPLY_SELF, + reply_delete_perm = perm.PERM_DELETE_PROBLEM_SOLUTION_REPLY, + reply_delete_self_perm = perm.PERM_DELETE_PROBLEM_SOLUTION_REPLY_SELF ) }} {{ paginator.render(page, pcount) }} {% if drcount == 0 %} diff --git a/templates/record_detail.html b/templates/record_detail.html index 59acaffb..16d87879 100644 --- a/templates/record_detail.html +++ b/templates/record_detail.html @@ -27,7 +27,7 @@

    {{ _('Information') }}

    - {% if handler.has_perm(vj4.model.builtin.PERM_REJUDGE) %} + {% if handler.has_perm(perm.PERM_REJUDGE) %}
    {% endif %} - {% if handler.has_perm(vj4.model.builtin.PERM_CREATE_TRAINING) %} + {% if handler.has_perm(perm.PERM_CREATE_TRAINING) %}

    {{ _('Create Training Plan') }}

    diff --git a/templates/user_detail.html b/templates/user_detail.html index 6da54fc7..ceb00e4d 100644 --- a/templates/user_detail.html +++ b/templates/user_detail.html @@ -66,7 +66,7 @@ {{ vj4.constant.model.USER_GENDER_ICONS[handler.get_udoc_setting(udoc, 'gender')] }} {% endif %} - {% if handler.dudoc_has_perm(udoc, dudoc, vj4.model.builtin.PERM_MOD_BADGE) %} + {% if handler.dudoc_has_perm(udoc, dudoc, perm.PERM_MOD_BADGE) %}
    diff --git a/templates/wiki_help.html b/templates/wiki_help.html index 315aa3e4..cbff4820 100644 --- a/templates/wiki_help.html +++ b/templates/wiki_help.html @@ -192,7 +192,7 @@
    {{ _('no_translation_warn')|safe }}

    如果您无法登录,请仔细想想,是不是用户名记错了。比如,自己原本想要注册的用户名已经被注册,所以使用了一个带有前和/或后缀的用户名。

    -

    如果您确信您的账号被盗或者忘记了账号和/或密码,请及时{{ _('Reset Password or Find Username') }}

    +

    如果您确信您的账号被盗或者忘记了账号和/或密码,请及时{{ _('Reset Password or Find Username') }}

    {% endblock %} diff --git a/yarn.lock b/yarn.lock index a1350591..58415de6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -153,6 +153,11 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== +blueimp-md5@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.13.0.tgz#07314b0c64dda0bf1733f96ce40d5af94eb28965" + integrity sha512-lmp0m647R5e77ORduxLW5mISIDcvgJZa52vMBv5uVI3UmSWTQjkJsZVBfaFqQPw/QFogJwvY6e3Gl9nP+Loe+Q== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -401,6 +406,11 @@ encodeurl@^1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= +entities@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + error-inject@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/error-inject/-/error-inject-1.0.0.tgz#e2b3d91b54aed672f309d950d154850fa11d4f37" @@ -651,6 +661,11 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +hljs@^6.2.3: + version "6.2.3" + resolved "https://registry.yarnpkg.com/hljs/-/hljs-6.2.3.tgz#d4d6208fa2a84f294956bc50f2c812e9cbd49bcc" + integrity sha1-1NYgj6KoTylJVrxQ8sgS6cvUm8w= + http-assert@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.4.1.tgz#c5f725d677aa7e873ef736199b89686cceb37878" @@ -839,6 +854,13 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= +katex@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.6.0.tgz#12418e09121c05c92041b6b3b9fb6bab213cb6f3" + integrity sha1-EkGOCRIcBckgQbazuftrqyE8tvM= + dependencies: + match-at "^0.1.0" + keygrip@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226" @@ -950,6 +972,13 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +linkify-it@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" + integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== + dependencies: + uc.micro "^1.0.1" + lodash@^4.17.14, lodash@^4.17.15: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" @@ -960,6 +989,34 @@ long@^4.0.0: resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== +markdown-it-katex@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/markdown-it-katex/-/markdown-it-katex-2.0.3.tgz#d7b86a1aea0b9d6496fab4e7919a18fdef589c39" + integrity sha1-17hqGuoLnWSW+rTnkZoY/e9YnDk= + dependencies: + katex "^0.6.0" + +markdown-it@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc" + integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg== + dependencies: + argparse "^1.0.7" + entities "~2.0.0" + linkify-it "^2.0.0" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +match-at@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/match-at/-/match-at-0.1.1.tgz#25d040d291777704d5e6556bbb79230ec2de0540" + integrity sha512-h4Yd392z9mST+dzc+yjuybOGFNOZjmXIPKWjxBd1Bb23r4SmDOsk2NYCU2BMUBGbSpZqwVsZYNq26QS3xfaT3Q== + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -1498,6 +1555,11 @@ type-is@^1.6.14, type-is@^1.6.16: media-typer "0.3.0" mime-types "~2.1.24" +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + unpipe@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"