mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
move docs, remove katex
This commit is contained in:
1 parent
da6002278d
commit
c4a13f2e27
27 files changed
+190
-550
No files matched your search
+1
-40
@@ -21,7 +21,7 @@ export const builtinModel = [
|
||||
export const builtinHandler = [
|
||||
'home', 'problem', 'record', 'judge', 'user',
|
||||
'contest', 'training', 'discussion', 'manage', 'import',
|
||||
'misc', 'homework', 'domain', 'wiki',
|
||||
'misc', 'homework', 'domain',
|
||||
];
|
||||
|
||||
export const builtinScript = [
|
||||
@@ -212,42 +212,3 @@ export async function script(pending: string[], fail: string[], active: string[]
|
||||
active.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
export async function wiki(pending: string[], fail: string[]) {
|
||||
for (const i of pending) {
|
||||
const p = path.resolve(i, 'wiki');
|
||||
if (fs.existsSync(p) && fs.statSync(p).isDirectory() && !fail.includes(i)) {
|
||||
try {
|
||||
const categories = fs.readdirSync(p);
|
||||
for (const category of categories) {
|
||||
if (!fs.statSync(p).isDirectory()) return;
|
||||
const pages = fs.readdirSync(path.join(p, category));
|
||||
if (!global.Hydro.wiki[category]) global.Hydro.wiki[category] = {};
|
||||
for (const page of pages) {
|
||||
const c = fs.readFileSync(path.join(p, category, page)).toString().split('\n');
|
||||
const pagename = page.split('.')[0];
|
||||
global.Hydro.wiki[category][pagename] = [];
|
||||
let content = null;
|
||||
for (let j = 0; j < c.length; j++) {
|
||||
const line = c[j];
|
||||
if (line.startsWith('# ')) {
|
||||
if (content) global.Hydro.wiki[category][pagename].push(content);
|
||||
content = {};
|
||||
const t = line.split('# ')[1].split('|');
|
||||
[content.title, content.id] = t.map((q) => q.trim());
|
||||
content.content = '';
|
||||
} else {
|
||||
content.content = `${content.content}${line}\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(`Wiki init: ${i}`);
|
||||
} catch (e) {
|
||||
fail.push(i);
|
||||
console.error(`Wiki Load Fail: ${i}`);
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,6 @@ import Router from 'koa-router';
|
||||
import cache from 'koa-static-cache';
|
||||
import nunjucks from 'nunjucks';
|
||||
import mongodb from 'mongodb';
|
||||
import parse from 'yargs-parser';
|
||||
|
||||
const argv = parse(process.argv.slice(2));
|
||||
|
||||
class Loader {
|
||||
getSource(name: string) { // eslint-disable-line class-methods-use-this
|
||||
@@ -110,7 +107,7 @@ export function load() {
|
||||
ctx.body = await render('setup.html');
|
||||
ctx.response.type = 'text/html';
|
||||
});
|
||||
const listenPort = argv.port || 8888;
|
||||
const listenPort = global.argv.port || 8888;
|
||||
router.post('/', async (ctx) => {
|
||||
const {
|
||||
host, port, name, username, password,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
/* eslint-disable import/no-dynamic-require */
|
||||
import {
|
||||
locale, template, lib, service, model, handler, script, setting, wiki, uistatic,
|
||||
locale, template, lib, service, model, handler, script, setting, uistatic,
|
||||
builtinLib, builtinScript, builtinHandler, builtinModel,
|
||||
} from './common';
|
||||
|
||||
@@ -17,7 +17,6 @@ export async function load(call, args) {
|
||||
locale(pending, fail),
|
||||
template(pending, fail),
|
||||
uistatic(pending, fail),
|
||||
wiki(pending, fail),
|
||||
]);
|
||||
const bus = require('../service/bus');
|
||||
await new Promise((resolve) => {
|
||||
|
||||
@@ -103,10 +103,11 @@ class SwitchLanguageHandler extends Handler {
|
||||
}
|
||||
|
||||
class MarkdownHandler extends Handler {
|
||||
async post({ text, safe = true }) {
|
||||
this.response.body = safe
|
||||
? markdown.safe.render(text)
|
||||
: markdown.unsafe.render(text);
|
||||
async post({ text, html = false, inline = false }) {
|
||||
this.response.body = inline
|
||||
? markdown.renderInline(text, html)
|
||||
: markdown.render(text, html);
|
||||
this.response.type = 'text/html';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -355,7 +355,7 @@ class ProblemEditHandler extends ProblemManageHandler {
|
||||
const pid = checkPid(this.request.body.pid);
|
||||
const pdoc = await problem.get(domainId, this.request.params.pid);
|
||||
await problem.edit(domainId, pdoc.docId, { title, content, pid });
|
||||
this.back();
|
||||
this.response.redirect = this.url('problem_detail', this.request.params.pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import { NotFoundError } from '../error';
|
||||
import {
|
||||
Route, Handler, Types, param,
|
||||
} from '../service/server';
|
||||
|
||||
class WikiHandler extends Handler {
|
||||
@param('category', Types.String, true)
|
||||
@param('page', Types.String)
|
||||
async get(domainId: string, category = 'wiki', page: string) {
|
||||
if (!global.Hydro.wiki[category]) throw new NotFoundError(category);
|
||||
if (!global.Hydro.wiki[category][page]) throw new NotFoundError(category, page);
|
||||
const contents = global.Hydro.wiki[category][page];
|
||||
const pages = Object.keys(global.Hydro.wiki[category]);
|
||||
const path = [
|
||||
['Hydro', 'homepage'],
|
||||
[`wiki_${category}`, null],
|
||||
[`wiki_${category}_${page}`, null],
|
||||
];
|
||||
this.response.body = {
|
||||
path, contents, pages, page_name: `wiki_${category}_${page}`,
|
||||
};
|
||||
this.response.template = 'wiki.html';
|
||||
}
|
||||
}
|
||||
|
||||
export async function apply() {
|
||||
Route('wiki', '/wiki/:page', WikiHandler);
|
||||
Route('wiki_with_category', '/wiki/:category/:page', WikiHandler);
|
||||
}
|
||||
|
||||
global.Hydro.handler.wiki = apply;
|
||||
@@ -281,7 +281,6 @@ declare global {
|
||||
[key: string]: any
|
||||
},
|
||||
stat: any,
|
||||
wiki: { [category: string]: { [page: string]: any } },
|
||||
ui: {
|
||||
manifest: Dict<string>,
|
||||
nav: any,
|
||||
|
||||
+19
-37
@@ -17,21 +17,15 @@ belong to the previous footnote.
|
||||
import Footnote from 'markdown-it-footnote';
|
||||
// ==Highlight==
|
||||
import Mark from 'markdown-it-mark';
|
||||
// :::warn This page requires javascript. :::
|
||||
// :::record-pass Accepted :::
|
||||
import Container from 'markdown-it-container';
|
||||
|
||||
import TOC from 'markdown-it-table-of-contents';
|
||||
|
||||
import Anchor from 'markdown-it-anchor';
|
||||
import katex from '../markdown/katex';
|
||||
|
||||
const md = MarkdownIt();
|
||||
|
||||
require('prismjs/components/index');
|
||||
|
||||
type Plugin = MarkdownIt.PluginSimple | MarkdownIt.PluginWithOptions | MarkdownIt.PluginWithParams;
|
||||
|
||||
class Markdown extends MarkdownIt {
|
||||
constructor(safe) {
|
||||
constructor() {
|
||||
super({
|
||||
linkify: true,
|
||||
highlight(str, lang) {
|
||||
@@ -42,44 +36,32 @@ class Markdown extends MarkdownIt {
|
||||
}
|
||||
return '';
|
||||
},
|
||||
html: !safe,
|
||||
});
|
||||
this.linkify.tlds('.py', false);
|
||||
this.use(katex);
|
||||
this.use(Imsize);
|
||||
this.use(Footnote);
|
||||
this.use(Mark);
|
||||
this.use(Anchor);
|
||||
this.use(TOC);
|
||||
const RE_CONTAINER = /^(note|warn|record-pending|record-progress|record-fail|record-pass|record-ignored)\s+(.*?):::(.*)$/;
|
||||
const CONTAINER_MAP = {
|
||||
note: ['<blockquote class="note">', '</blockquote>'],
|
||||
warn: ['<blockquote class="warn">', '</blockquote>'],
|
||||
'record-pending': ['<span class="record-status--text pending">', '</span>'],
|
||||
'record-progress': ['<span class="record-status--text progress">', '</span>'],
|
||||
'record-fail': ['<span class="record-status--text fail">', '</span>'],
|
||||
'record-pass': ['<span class="record-status--text pass">', '</span>'],
|
||||
'record-ignored': ['<span class="record-status--text ignored">', '</span>'],
|
||||
};
|
||||
this.use(Container, 'blockquote', {
|
||||
validate(params) {
|
||||
return params.trim().match(RE_CONTAINER);
|
||||
},
|
||||
render(tokens, idx) {
|
||||
const m = tokens[idx].info.trim().match(RE_CONTAINER);
|
||||
if (!m) return '';
|
||||
if (CONTAINER_MAP[m[1]]) {
|
||||
return `${CONTAINER_MAP[m[1]][0]}${md.utils.escapeHtml(m[2])}\n${CONTAINER_MAP[m[1]][1]}\n${md.utils.escapeHtml(m[3])}`;
|
||||
}
|
||||
return `[${m[1]}]\n${md.utils.escapeHtml(m[2])}\n[/${m[1]}]\n${md.utils.escapeHtml(m[3])}`;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const safe = new Markdown(true);
|
||||
export const unsafe = new Markdown(false);
|
||||
export const md = new Markdown();
|
||||
|
||||
export function plugin(func: Plugin, ...args: any[]) {
|
||||
md.use(func, ...args);
|
||||
}
|
||||
|
||||
export function render(text: string, html = false) {
|
||||
md.set({ html: !!html });
|
||||
return md.render(text);
|
||||
}
|
||||
|
||||
export function renderInline(text: string, html = false) {
|
||||
md.set({ html: !!html });
|
||||
return md.renderInline(text);
|
||||
}
|
||||
|
||||
global.Hydro.lib.markdown = {
|
||||
safe, unsafe,
|
||||
md, plugin, render, renderInline,
|
||||
};
|
||||
@@ -35,10 +35,7 @@ class Nunjucks extends nunjucks.Environment {
|
||||
this.addFilter('json', (self) => JSON.stringify(self), false);
|
||||
this.addFilter('serialize', (self, ignoreFunction = true) => serialize(self, { ignoreFunction }));
|
||||
this.addFilter('assign', (self, data) => Object.assign(self, data));
|
||||
this.addFilter('markdown', (self, safe = true) => {
|
||||
if (safe) return markdown.safe.render(self);
|
||||
return markdown.unsafe.render(self);
|
||||
});
|
||||
this.addFilter('markdown', (self, html = false) => markdown.render(self, html));
|
||||
this.addFilter('ansi', (self) => misc.ansiToHtml(self));
|
||||
this.addFilter('base64_encode', (s) => Buffer.from(s).toString('base64'));
|
||||
this.addFilter('bitand', (self, val) => self & val);
|
||||
|
||||
+2
-4
@@ -8,11 +8,10 @@ import os from 'os';
|
||||
import path from 'path';
|
||||
import cluster from 'cluster';
|
||||
import fs from 'fs-extra';
|
||||
import parse from 'yargs-parser';
|
||||
import { argv } from 'yargs';
|
||||
import AdmZip from 'adm-zip';
|
||||
|
||||
global.argv = parse(process.argv.slice(2));
|
||||
|
||||
global.argv = argv;
|
||||
global.Hydro = {
|
||||
stat: { reqCount: 0 },
|
||||
handler: {},
|
||||
@@ -23,7 +22,6 @@ global.Hydro = {
|
||||
script: {},
|
||||
// @ts-ignore
|
||||
lib: {},
|
||||
wiki: {},
|
||||
ui: {
|
||||
manifest: {},
|
||||
nav: [],
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
// https://github.com/hydro-dev/markdown-it-katex/blob/master/index.js
|
||||
import katex from 'katex';
|
||||
import MarkdownIt from 'markdown-it';
|
||||
|
||||
function isValidDelim(state, pos: number) {
|
||||
const max = state.posMax;
|
||||
const prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
|
||||
const nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;
|
||||
let canOpen = true;
|
||||
let canClose = true;
|
||||
if (prevChar === 0x20/* " " */ || prevChar === 0x09
|
||||
||/* \t */ (nextChar >= 0x30/* "0" */ && nextChar <= 0x39/* "9" */)) {
|
||||
canClose = false;
|
||||
}
|
||||
if (nextChar === 0x20/* " " */ || nextChar === 0x09/* \t */) {
|
||||
canOpen = false;
|
||||
}
|
||||
return { canOpen, canClose };
|
||||
}
|
||||
|
||||
function mathInline(state, silent: boolean) {
|
||||
let match;
|
||||
let res;
|
||||
let pos;
|
||||
if (state.src[state.pos] !== '$') return false;
|
||||
res = isValidDelim(state, state.pos);
|
||||
if (!res.canOpen) {
|
||||
if (!silent) state.pending += '$';
|
||||
state.pos += 1;
|
||||
return true;
|
||||
}
|
||||
const start = state.pos + 1;
|
||||
match = start;
|
||||
// eslint-disable-next-line no-cond-assign
|
||||
while ((match = state.src.indexOf('$', match)) !== -1) {
|
||||
pos = match - 1;
|
||||
while (state.src[pos] === '\\') pos -= 1;
|
||||
if (((match - pos) % 2) === 1) break;
|
||||
match += 1;
|
||||
}
|
||||
if (match === -1) {
|
||||
if (!silent) state.pending += '$';
|
||||
state.pos = start;
|
||||
return true;
|
||||
}
|
||||
if (match - start === 0) {
|
||||
if (!silent) state.pending += '$$';
|
||||
state.pos = start + 1;
|
||||
return true;
|
||||
}
|
||||
res = isValidDelim(state, match);
|
||||
if (!res.can_close) {
|
||||
if (!silent) state.pending += '$';
|
||||
state.pos = start;
|
||||
return true;
|
||||
}
|
||||
if (!silent) {
|
||||
const token = state.push('math_inline', 'math', 0);
|
||||
token.markup = '$';
|
||||
token.content = state.src.slice(start, match);
|
||||
}
|
||||
state.pos = match + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
function mathBlock(state, start, end, silent) {
|
||||
let lastLine;
|
||||
let next;
|
||||
let lastPos;
|
||||
let found = false;
|
||||
let pos = state.bMarks[start] + state.tShift[start];
|
||||
let max = state.eMarks[start];
|
||||
if (pos + 2 > max) return false;
|
||||
if (state.src.slice(pos, pos + 2) !== '$$') return false;
|
||||
pos += 2;
|
||||
let firstLine = state.src.slice(pos, max);
|
||||
if (silent) return true;
|
||||
if (firstLine.trim().slice(-2) === '$$') {
|
||||
firstLine = firstLine.trim().slice(0, -2);
|
||||
found = true;
|
||||
}
|
||||
for (next = start; !found;) {
|
||||
next++;
|
||||
if (next >= end) break;
|
||||
pos = state.bMarks[next] + state.tShift[next];
|
||||
max = state.eMarks[next];
|
||||
if (pos < max && state.tShift[next] < state.blkIndent) break;
|
||||
if (state.src.slice(pos, max).trim().slice(-2) === '$$') {
|
||||
lastPos = state.src.slice(0, max).lastIndexOf('$$');
|
||||
lastLine = state.src.slice(pos, lastPos);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
state.line = next + 1;
|
||||
const token = state.push('math_block', 'math', 0);
|
||||
token.block = true;
|
||||
token.content = (firstLine && firstLine.trim() ? `${firstLine}\n` : '')
|
||||
+ state.getLines(start + 1, next, state.tShift[start], true)
|
||||
+ (lastLine && lastLine.trim() ? lastLine : '');
|
||||
token.map = [start, state.line];
|
||||
token.markup = '$$';
|
||||
return true;
|
||||
}
|
||||
|
||||
export default function plugin(md: MarkdownIt, options) {
|
||||
options = options || {};
|
||||
function katexInline(latex: string) {
|
||||
options.displayMode = false;
|
||||
try {
|
||||
return katex.renderToString(latex, options);
|
||||
} catch (error) {
|
||||
if (options.throwOnError) console.log(error);
|
||||
return latex;
|
||||
}
|
||||
}
|
||||
function inlineRenderer(tokens, idx) {
|
||||
return katexInline(tokens[idx].content);
|
||||
}
|
||||
function katexBlock(latex: string) {
|
||||
options.displayMode = true;
|
||||
try {
|
||||
return `<p>${katex.renderToString(latex, options)}</p>`;
|
||||
} catch (error) {
|
||||
if (options.throwOnError) console.log(error);
|
||||
return latex;
|
||||
}
|
||||
}
|
||||
function blockRenderer(tokens, idx) {
|
||||
return `${katexBlock(tokens[idx].content)}\n`;
|
||||
}
|
||||
md.inline.ruler.after('escape', 'math_inline', mathInline);
|
||||
md.block.ruler.after('blockquote', 'math_block', mathBlock, {
|
||||
alt: ['paragraph', 'reference', 'blockquote', 'list'],
|
||||
});
|
||||
md.renderer.rules.math_inline = inlineRenderer;
|
||||
md.renderer.rules.math_block = blockRenderer;
|
||||
}
|
||||
+11
-11
@@ -131,17 +131,17 @@ SystemSetting(
|
||||
Setting('setting_oauth', 'oauth.googleappid', null, null, 'text', 'Google Oauth ClientID', null),
|
||||
Setting('setting_oauth', 'oauth.googlesecret', null, null, 'text', 'Google Oauth Secret', null, FLAG_SECRET),
|
||||
Setting('setting_proxy', 'proxy', null, null, 'text', 'Proxy Server URL'),
|
||||
Setting('setting_constant', 'PROBLEM_PER_PAGE', null, 100, 'number', 'Problems per Page'),
|
||||
Setting('setting_constant', 'CONTEST_PER_PAGE', null, 20, 'number', 'Contests per Page'),
|
||||
Setting('setting_constant', 'DISCUSSION_PER_PAGE', null, 50, 'number', 'Discussion per Page'),
|
||||
Setting('setting_constant', 'RECORD_PER_PAGE', null, 100, 'number', 'Record per Page'),
|
||||
Setting('setting_constant', 'SOLUTION_PER_PAGE', null, 20, 'number', 'Solutions per Page'),
|
||||
Setting('setting_constant', 'TRAINING_PER_PAGE', null, 10, 'number', 'Training per Page'),
|
||||
Setting('setting_constant', 'REPLY_PER_PAGE', null, 50, 'number', 'Reply per Page'),
|
||||
Setting('setting_constant', 'HOMEWORK_ON_MAIN', null, 5, 'number', 'HOMEWORK_ON_MAIN'),
|
||||
Setting('setting_constant', 'DISCUSSION_ON_MAIN', null, 20, 'number', 'DISCUSSION_ON_MAIN'),
|
||||
Setting('setting_constant', 'CONTEST_ON_MAIN', null, 10, 'number', 'CONTEST_ON_MAIN'),
|
||||
Setting('setting_constant', 'TRAINING_ON_MAIN', null, 10, 'number', 'TRAINING_ON_MAIN'),
|
||||
Setting('setting_constant', 'PROBLEM_PER_PAGE', null, 100, 'number', 'Problems per Page', null, FLAG_HIDDEN),
|
||||
Setting('setting_constant', 'CONTEST_PER_PAGE', null, 20, 'number', 'Contests per Page', null, FLAG_HIDDEN),
|
||||
Setting('setting_constant', 'DISCUSSION_PER_PAGE', null, 50, 'number', 'Discussion per Page', null, FLAG_HIDDEN),
|
||||
Setting('setting_constant', 'RECORD_PER_PAGE', null, 100, 'number', 'Record per Page', null, FLAG_HIDDEN),
|
||||
Setting('setting_constant', 'SOLUTION_PER_PAGE', null, 20, 'number', 'Solutions per Page', null, FLAG_HIDDEN),
|
||||
Setting('setting_constant', 'TRAINING_PER_PAGE', null, 10, 'number', 'Training per Page', null, FLAG_HIDDEN),
|
||||
Setting('setting_constant', 'REPLY_PER_PAGE', null, 50, 'number', 'Reply per Page', null, FLAG_HIDDEN),
|
||||
Setting('setting_constant', 'HOMEWORK_ON_MAIN', null, 5, 'number', 'HOMEWORK_ON_MAIN', null, FLAG_HIDDEN),
|
||||
Setting('setting_constant', 'DISCUSSION_ON_MAIN', null, 20, 'number', 'DISCUSSION_ON_MAIN', null, FLAG_HIDDEN),
|
||||
Setting('setting_constant', 'CONTEST_ON_MAIN', null, 10, 'number', 'CONTEST_ON_MAIN', null, FLAG_HIDDEN),
|
||||
Setting('setting_constant', 'TRAINING_ON_MAIN', null, 10, 'number', 'TRAINING_ON_MAIN', null, FLAG_HIDDEN),
|
||||
Setting('setting_storage', 'db.ver', null, 1, 'number', 'Database version', null, FLAG_DISABLED | FLAG_HIDDEN),
|
||||
Setting('setting_storage', 'user', null, 1, 'number', 'User Counter', null, FLAG_DISABLED | FLAG_HIDDEN),
|
||||
);
|
||||
|
||||
@@ -13,7 +13,6 @@ import Router from 'koa-router';
|
||||
import cache from 'koa-static-cache';
|
||||
import sockjs from 'sockjs';
|
||||
import serialize, { SerializeJSOptions } from 'serialize-javascript';
|
||||
import parse from 'yargs-parser';
|
||||
import { lrucache } from '../utils';
|
||||
import { User, DomainDoc } from '../interface';
|
||||
import {
|
||||
@@ -32,7 +31,6 @@ import * as blacklist from '../model/blacklist';
|
||||
import * as token from '../model/token';
|
||||
import * as opcount from '../model/opcount';
|
||||
|
||||
const argv = parse(process.argv.slice(2));
|
||||
const app = new Koa();
|
||||
let server;
|
||||
const router = new Router();
|
||||
@@ -774,8 +772,8 @@ export async function start() {
|
||||
}
|
||||
app.use(router.routes()).use(router.allowedMethods());
|
||||
Route('notfound_handler', '*', Handler);
|
||||
server.listen(argv.port || port);
|
||||
console.log('Server listening at: %s', argv.port || port);
|
||||
server.listen(global.argv.port || port);
|
||||
console.log('Server listening at: %s', global.argv.port || port);
|
||||
}
|
||||
|
||||
global.Hydro.service.server = {
|
||||
|
||||
Reference in new issue
Block a user