2024-10-10
This commit is contained in:
19
web/template/sidebar/js/MathJax.js
Normal file
19
web/template/sidebar/js/MathJax.js
Normal file
File diff suppressed because one or more lines are too long
1
web/template/sidebar/js/auto-render.min.js
vendored
Normal file
1
web/template/sidebar/js/auto-render.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,function(e){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=1)}([function(t,r){t.exports=e},function(e,t,r){"use strict";r.r(t);var n=r(0),o=r.n(n),a=function(e,t,r){for(var n=r,o=0,a=e.length;n<t.length;){var i=t[n];if(o<=0&&t.slice(n,n+a)===e)return n;"\\"===i?n++:"{"===i?o++:"}"===i&&o--,n++}return-1},i=function(e,t,r,n){for(var o=[],i=0;i<e.length;i++)if("text"===e[i].type){var l=e[i].data,d=!0,s=0,f=void 0;for(-1!==(f=l.indexOf(t))&&(s=f,o.push({type:"text",data:l.slice(0,s)}),d=!1);;){if(d){if(-1===(f=l.indexOf(t,s)))break;o.push({type:"text",data:l.slice(s,f)}),s=f}else{if(-1===(f=a(r,l,s+t.length)))break;o.push({type:"math",data:l.slice(s+t.length,f),rawData:l.slice(s,f+r.length),display:n}),s=f+r.length}d=!d}o.push({type:"text",data:l.slice(s)})}else o.push(e[i]);return o},l=function(e,t){var r=function(e,t){for(var r=[{type:"text",data:e}],n=0;n<t.length;n++){var o=t[n];r=i(r,o.left,o.right,o.display||!1)}return r}(e,t.delimiters);if(1===r.length&&"text"===r[0].type)return null;for(var n=document.createDocumentFragment(),a=0;a<r.length;a++)if("text"===r[a].type)n.appendChild(document.createTextNode(r[a].data));else{var l=document.createElement("span"),d=r[a].data;t.displayMode=r[a].display;try{t.preProcess&&(d=t.preProcess(d)),o.a.render(d,l,t)}catch(e){if(!(e instanceof o.a.ParseError))throw e;t.errorCallback("KaTeX auto-render: Failed to parse `"+r[a].data+"` with ",e),n.appendChild(document.createTextNode(r[a].rawData));continue}n.appendChild(l)}return n};t.default=function(e,t){if(!e)throw new Error("No element provided to render");var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);r.delimiters=r.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}],r.ignoredTags=r.ignoredTags||["script","noscript","style","textarea","pre","code","option"],r.ignoredClasses=r.ignoredClasses||[],r.errorCallback=r.errorCallback||console.error,r.macros=r.macros||{},function e(t,r){for(var n=0;n<t.childNodes.length;n++){var o=t.childNodes[n];if(3===o.nodeType){var a=l(o.textContent,r);a&&(n+=a.childNodes.length-1,t.replaceChild(a,o))}else 1===o.nodeType&&function(){var t=" "+o.className+" ";-1===r.ignoredTags.indexOf(o.nodeName.toLowerCase())&&r.ignoredClasses.every(function(e){return-1===t.indexOf(" "+e+" ")})&&e(o,r)}()}}(e,r)}}]).default});
|
||||
7
web/template/sidebar/js/bootstrap.min.js
vendored
Normal file
7
web/template/sidebar/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
45
web/template/sidebar/js/echarts.min.js
vendored
Normal file
45
web/template/sidebar/js/echarts.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
8
web/template/sidebar/js/html5shiv.js
vendored
Normal file
8
web/template/sidebar/js/html5shiv.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||
*/
|
||||
(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
|
||||
a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/[\w\-]+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}</style>";
|
||||
c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
|
||||
"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:"3.7.0",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);
|
||||
if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);
|
||||
2
web/template/sidebar/js/jquery.min.js
vendored
Normal file
2
web/template/sidebar/js/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
349
web/template/sidebar/js/jsmind.draggable.js
Normal file
349
web/template/sidebar/js/jsmind.draggable.js
Normal file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Released under BSD License
|
||||
* Copyright (c) 2014-2015 hizzgdev@163.com
|
||||
*
|
||||
* Project Home:
|
||||
* https://github.com/hizzgdev/jsmind/
|
||||
*/
|
||||
|
||||
(function($w){
|
||||
'use strict';
|
||||
var $d = $w.document;
|
||||
var __name__ = 'jsMind';
|
||||
var jsMind = $w[__name__];
|
||||
if(!jsMind){return;}
|
||||
if(typeof jsMind.draggable != 'undefined'){return;}
|
||||
|
||||
var jdom = jsMind.util.dom;
|
||||
var jcanvas = jsMind.util.canvas;
|
||||
|
||||
var clear_selection = 'getSelection' in $w ? function(){
|
||||
$w.getSelection().removeAllRanges();
|
||||
} : function(){
|
||||
$d.selection.empty();
|
||||
};
|
||||
|
||||
var options = {
|
||||
line_width : 5,
|
||||
lookup_delay : 500,
|
||||
lookup_interval : 80
|
||||
};
|
||||
|
||||
jsMind.draggable = function(jm){
|
||||
this.jm = jm;
|
||||
this.e_canvas = null;
|
||||
this.canvas_ctx = null;
|
||||
this.shadow = null;
|
||||
this.shadow_w = 0;
|
||||
this.shadow_h = 0;
|
||||
this.active_node = null;
|
||||
this.target_node = null;
|
||||
this.target_direct = null;
|
||||
this.client_w = 0;
|
||||
this.client_h = 0;
|
||||
this.offset_x = 0;
|
||||
this.offset_y = 0;
|
||||
this.hlookup_delay = 0;
|
||||
this.hlookup_timer = 0;
|
||||
this.capture = false;
|
||||
this.moved = false;
|
||||
};
|
||||
|
||||
jsMind.draggable.prototype = {
|
||||
init:function(){
|
||||
this._create_canvas();
|
||||
this._create_shadow();
|
||||
this._event_bind();
|
||||
},
|
||||
|
||||
resize:function(){
|
||||
this.jm.view.e_nodes.appendChild(this.shadow);
|
||||
this.e_canvas.width=this.jm.view.size.w;
|
||||
this.e_canvas.height=this.jm.view.size.h;
|
||||
},
|
||||
|
||||
_create_canvas:function(){
|
||||
var c = $d.createElement('canvas');
|
||||
this.jm.view.e_panel.appendChild(c);
|
||||
var ctx = c.getContext('2d');
|
||||
this.e_canvas = c;
|
||||
this.canvas_ctx = ctx;
|
||||
},
|
||||
|
||||
_create_shadow:function(){
|
||||
var s = $d.createElement('jmnode');
|
||||
s.style.visibility = 'hidden';
|
||||
s.style.zIndex = '3';
|
||||
s.style.cursor = 'move';
|
||||
s.style.opacity= '0.7';
|
||||
this.shadow = s;
|
||||
},
|
||||
|
||||
reset_shadow:function(el){
|
||||
var s = this.shadow.style;
|
||||
this.shadow.innerHTML = el.innerHTML;
|
||||
s.left = el.style.left;
|
||||
s.top = el.style.top;
|
||||
s.width = el.style.width;
|
||||
s.height = el.style.height;
|
||||
s.backgroundImage = el.style.backgroundImage;
|
||||
s.backgroundSize = el.style.backgroundSize;
|
||||
s.transform = el.style.transform;
|
||||
this.shadow_w = this.shadow.clientWidth;
|
||||
this.shadow_h = this.shadow.clientHeight;
|
||||
|
||||
},
|
||||
|
||||
show_shadow:function(){
|
||||
if(!this.moved){
|
||||
this.shadow.style.visibility = 'visible';
|
||||
}
|
||||
},
|
||||
|
||||
hide_shadow:function(){
|
||||
this.shadow.style.visibility = 'hidden';
|
||||
},
|
||||
|
||||
clear_lines:function(){
|
||||
jcanvas.clear(this.canvas_ctx, 0, 0, this.jm.view.size.w, this.jm.view.size.h);
|
||||
},
|
||||
|
||||
_magnet_shadow:function(node){
|
||||
if(!!node){
|
||||
this.canvas_ctx.lineWidth = options.line_width;
|
||||
this.canvas_ctx.strokeStyle = 'rgba(0,0,0,0.3)';
|
||||
this.canvas_ctx.lineCap = 'round';
|
||||
this.clear_lines();
|
||||
jcanvas.lineto(this.canvas_ctx,
|
||||
node.sp.x,
|
||||
node.sp.y,
|
||||
node.np.x,
|
||||
node.np.y);
|
||||
}
|
||||
},
|
||||
|
||||
_lookup_close_node:function(){
|
||||
var root = this.jm.get_root();
|
||||
var root_location = root.get_location();
|
||||
var root_size = root.get_size();
|
||||
var root_x = root_location.x + root_size.w/2;
|
||||
|
||||
var sw = this.shadow_w;
|
||||
var sh = this.shadow_h;
|
||||
var sx = this.shadow.offsetLeft;
|
||||
var sy = this.shadow.offsetTop;
|
||||
|
||||
var ns,nl;
|
||||
|
||||
var direct = (sx + sw/2)>=root_x ?
|
||||
jsMind.direction.right : jsMind.direction.left;
|
||||
var nodes = this.jm.mind.nodes;
|
||||
var node = null;
|
||||
var min_distance = Number.MAX_VALUE;
|
||||
var distance = 0;
|
||||
var closest_node = null;
|
||||
var closest_p = null;
|
||||
var shadow_p = null;
|
||||
for(var nodeid in nodes){
|
||||
var np,sp;
|
||||
node = nodes[nodeid];
|
||||
if(node.isroot || node.direction == direct){
|
||||
if(node.id == this.active_node.id){
|
||||
continue;
|
||||
}
|
||||
ns = node.get_size();
|
||||
nl = node.get_location();
|
||||
if(direct == jsMind.direction.right){
|
||||
if(sx-nl.x-ns.w<=0){continue;}
|
||||
distance = Math.abs(sx-nl.x-ns.w) + Math.abs(sy+sh/2-nl.y-ns.h/2);
|
||||
np = {x:nl.x+ns.w-options.line_width,y:nl.y+ns.h/2};
|
||||
sp = {x:sx+options.line_width,y:sy+sh/2};
|
||||
}else{
|
||||
if(nl.x-sx-sw<=0){continue;}
|
||||
distance = Math.abs(sx+sw-nl.x) + Math.abs(sy+sh/2-nl.y-ns.h/2);
|
||||
np = {x:nl.x+options.line_width,y:nl.y+ns.h/2};
|
||||
sp = {x:sx+sw-options.line_width,y:sy+sh/2};
|
||||
}
|
||||
if(distance < min_distance){
|
||||
closest_node = node;
|
||||
closest_p = np;
|
||||
shadow_p = sp;
|
||||
min_distance = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
var result_node = null;
|
||||
if(!!closest_node){
|
||||
result_node = {
|
||||
node:closest_node,
|
||||
direction:direct,
|
||||
sp:shadow_p,
|
||||
np:closest_p
|
||||
};
|
||||
}
|
||||
return result_node;
|
||||
},
|
||||
|
||||
lookup_close_node:function(){
|
||||
var node_data = this._lookup_close_node();
|
||||
if(!!node_data){
|
||||
this._magnet_shadow(node_data);
|
||||
this.target_node = node_data.node;
|
||||
this.target_direct = node_data.direction;
|
||||
}
|
||||
},
|
||||
|
||||
_event_bind:function(){
|
||||
var jd = this;
|
||||
var container = this.jm.view.container;
|
||||
jdom.add_event(container,'mousedown',function(e){
|
||||
var evt = e || event;
|
||||
jd.dragstart.call(jd,evt);
|
||||
});
|
||||
jdom.add_event(container,'mousemove',function(e){
|
||||
var evt = e || event;
|
||||
jd.drag.call(jd,evt);
|
||||
});
|
||||
jdom.add_event(container,'mouseup',function(e){
|
||||
var evt = e || event;
|
||||
jd.dragend.call(jd,evt);
|
||||
});
|
||||
jdom.add_event(container,'touchstart',function(e){
|
||||
var evt = e || event;
|
||||
jd.dragstart.call(jd,evt);
|
||||
});
|
||||
jdom.add_event(container,'touchmove',function(e){
|
||||
var evt = e || event;
|
||||
jd.drag.call(jd,evt);
|
||||
});
|
||||
jdom.add_event(container,'touchend',function(e){
|
||||
var evt = e || event;
|
||||
jd.dragend.call(jd,evt);
|
||||
});
|
||||
},
|
||||
|
||||
dragstart:function(e){
|
||||
if(!this.jm.get_editable()){return;}
|
||||
if(this.capture){return;}
|
||||
this.active_node = null;
|
||||
|
||||
var jview = this.jm.view;
|
||||
var el = e.target || event.srcElement;
|
||||
if(el.tagName.toLowerCase() != 'jmnode'){return;}
|
||||
var nodeid = jview.get_binded_nodeid(el);
|
||||
if(!!nodeid){
|
||||
var node = this.jm.get_node(nodeid);
|
||||
if(!node.isroot){
|
||||
this.reset_shadow(el);
|
||||
this.active_node = node;
|
||||
this.offset_x = (e.clientX || e.touches[0].clientX) - el.offsetLeft;
|
||||
this.offset_y = (e.clientY || e.touches[0].clientY) - el.offsetTop;
|
||||
this.client_hw = Math.floor(el.clientWidth/2);
|
||||
this.client_hh = Math.floor(el.clientHeight/2);
|
||||
if(this.hlookup_delay != 0){
|
||||
$w.clearTimeout(this.hlookup_delay);
|
||||
}
|
||||
if(this.hlookup_timer != 0){
|
||||
$w.clearInterval(this.hlookup_timer);
|
||||
}
|
||||
var jd = this;
|
||||
this.hlookup_delay = $w.setTimeout(function(){
|
||||
jd.hlookup_delay = 0;
|
||||
jd.hlookup_timer = $w.setInterval(function(){
|
||||
jd.lookup_close_node.call(jd);
|
||||
},options.lookup_interval);
|
||||
},options.lookup_delay);
|
||||
this.capture = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
drag:function(e){
|
||||
if(!this.jm.get_editable()){return;}
|
||||
if(this.capture){
|
||||
e.preventDefault();
|
||||
this.show_shadow();
|
||||
this.moved = true;
|
||||
clear_selection();
|
||||
var px = (e.clientX || e.touches[0].clientX) - this.offset_x;
|
||||
var py = (e.clientY || e.touches[0].clientY) - this.offset_y;
|
||||
var cx = px + this.client_hw;
|
||||
var cy = py + this.client_hh;
|
||||
this.shadow.style.left = px + 'px';
|
||||
this.shadow.style.top = py + 'px';
|
||||
clear_selection();
|
||||
}
|
||||
},
|
||||
|
||||
dragend:function(e){
|
||||
if(!this.jm.get_editable()){return;}
|
||||
if(this.capture){
|
||||
if(this.hlookup_delay != 0){
|
||||
$w.clearTimeout(this.hlookup_delay);
|
||||
this.hlookup_delay = 0;
|
||||
this.clear_lines();
|
||||
}
|
||||
if(this.hlookup_timer != 0){
|
||||
$w.clearInterval(this.hlookup_timer);
|
||||
this.hlookup_timer = 0;
|
||||
this.clear_lines();
|
||||
}
|
||||
if(this.moved){
|
||||
var src_node = this.active_node;
|
||||
var target_node = this.target_node;
|
||||
var target_direct = this.target_direct;
|
||||
this.move_node(src_node,target_node,target_direct);
|
||||
}
|
||||
this.hide_shadow();
|
||||
}
|
||||
this.moved = false;
|
||||
this.capture = false;
|
||||
},
|
||||
|
||||
move_node:function(src_node,target_node,target_direct){
|
||||
var shadow_h = this.shadow.offsetTop;
|
||||
if(!!target_node && !!src_node && !jsMind.node.inherited(src_node, target_node)){
|
||||
// lookup before_node
|
||||
var sibling_nodes = target_node.children;
|
||||
var sc = sibling_nodes.length;
|
||||
var node = null;
|
||||
var delta_y = Number.MAX_VALUE;
|
||||
var node_before = null;
|
||||
var beforeid = '_last_';
|
||||
while(sc--){
|
||||
node = sibling_nodes[sc];
|
||||
if(node.direction == target_direct && node.id != src_node.id){
|
||||
var dy = node.get_location().y - shadow_h;
|
||||
if(dy > 0 && dy < delta_y){
|
||||
delta_y = dy;
|
||||
node_before = node;
|
||||
beforeid = '_first_';
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!!node_before){beforeid = node_before.id;}
|
||||
this.jm.move_node(src_node.id, beforeid, target_node.id, target_direct);
|
||||
}
|
||||
this.active_node = null;
|
||||
this.target_node = null;
|
||||
this.target_direct = null;
|
||||
},
|
||||
|
||||
jm_event_handle:function(type,data){
|
||||
if(type === jsMind.event_type.resize){
|
||||
this.resize();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var draggable_plugin = new jsMind.plugin('draggable',function(jm){
|
||||
var jd = new jsMind.draggable(jm);
|
||||
jd.init();
|
||||
jm.add_event_listener(function(type,data){
|
||||
jd.jm_event_handle.call(jd,type,data);
|
||||
});
|
||||
});
|
||||
|
||||
jsMind.register_plugin(draggable_plugin);
|
||||
|
||||
})(window);
|
||||
2931
web/template/sidebar/js/jsmind.js
Normal file
2931
web/template/sidebar/js/jsmind.js
Normal file
File diff suppressed because it is too large
Load Diff
1
web/template/sidebar/js/katex.min.js
vendored
Normal file
1
web/template/sidebar/js/katex.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
269
web/template/sidebar/js/luogu.js
Normal file
269
web/template/sidebar/js/luogu.js
Normal file
@@ -0,0 +1,269 @@
|
||||
function load_jsmind() {
|
||||
var mind = {
|
||||
"meta": {"name": "luogu_mind","author": "luogu","version": "0.2",},
|
||||
"format": "node_array",
|
||||
"data": [
|
||||
{"id":"73","isroot":true,"topic":"ACM算法"},
|
||||
{"id":"2","parentid":"73","topic":"字符串","direction":"right","expanded":false},
|
||||
{"id":"101","parentid":"2","topic":"后缀自动机,SAM","expanded":false},
|
||||
{"id":"300","parentid":"2","topic":"字典树,Trie树","expanded":false},
|
||||
{"id":"301","parentid":"2","topic":"AC自动机","expanded":false},
|
||||
{"id":"302","parentid":"2","topic":"KMP","expanded":false},
|
||||
{"id":"303","parentid":"2","topic":"后缀数组,SA","expanded":false},
|
||||
{"id":"304","parentid":"2","topic":"后缀树","expanded":false},
|
||||
{"id":"305","parentid":"2","topic":"有限状态自动机","expanded":false},
|
||||
{"id":"306","parentid":"2","topic":"哈夫曼,Huffman","expanded":false},
|
||||
{"id":"307","parentid":"2","topic":"简单密码学","expanded":false},
|
||||
{"id":"325","parentid":"2","topic":"回文自动机PAM","expanded":false},
|
||||
{"id":"329","parentid":"2","topic":"Manacher算法","expanded":false},
|
||||
{"id":"3","parentid":"73","topic":"动态规划,动规,dp","direction":"right","expanded":false},
|
||||
{"id":"138","parentid":"3","topic":"动态规划初步","expanded":false},
|
||||
{"id":"139","parentid":"3","topic":"背包","expanded":false},
|
||||
{"id":"140","parentid":"3","topic":"环型动规,环型dp","expanded":false},
|
||||
{"id":"141","parentid":"3","topic":"数位动规,数位dp","expanded":false},
|
||||
{"id":"143","parentid":"3","topic":"多维状态","expanded":false},
|
||||
{"id":"144","parentid":"3","topic":"区间动规,区间dp","expanded":false},
|
||||
{"id":"145","parentid":"3","topic":"子母树","expanded":false},
|
||||
{"id":"146","parentid":"3","topic":"动态规划优化","expanded":false},
|
||||
{"id":"56","parentid":"146","topic":"单调队列"},
|
||||
{"id":"147","parentid":"146","topic":"降低维度,降维"},
|
||||
{"id":"148","parentid":"146","topic":"优先队列"},
|
||||
{"id":"149","parentid":"146","topic":"矩阵加速,矩阵优化"},
|
||||
{"id":"150","parentid":"146","topic":"斜率优化"},
|
||||
{"id":"151","parentid":"146","topic":"状态压缩,状压"},
|
||||
{"id":"153","parentid":"146","topic":"凸完全单调性,凸单调"},
|
||||
{"id":"154","parentid":"146","topic":"四边形不等式"},
|
||||
{"id":"152","parentid":"3","topic":"树形动规","expanded":false},
|
||||
{"id":"323","parentid":"3","topic":"插头dp","expanded":false},
|
||||
{"id":"4","parentid":"73","topic":"搜索","direction":"right","expanded":false},
|
||||
{"id":"126","parentid":"4","topic":"广度优先搜索,BFS","expanded":false},
|
||||
{"id":"127","parentid":"4","topic":"深度优先搜索,DFS","expanded":false},
|
||||
{"id":"128","parentid":"4","topic":"剪枝","expanded":false},
|
||||
{"id":"129","parentid":"4","topic":"记忆化搜索","expanded":false},
|
||||
{"id":"130","parentid":"4","topic":"启发式搜索","expanded":false},
|
||||
{"id":"132","parentid":"130","topic":"启发式迭代加深,IDA*"},
|
||||
{"id":"133","parentid":"130","topic":"Dancing Links"},
|
||||
{"id":"134","parentid":"130","topic":"爬山法"},
|
||||
{"id":"135","parentid":"130","topic":"模拟退火"},
|
||||
{"id":"137","parentid":"130","topic":"遗传"},
|
||||
{"id":"263","parentid":"130","topic":"A*算法"},
|
||||
{"id":"131","parentid":"4","topic":"迭代加深","expanded":false},
|
||||
{"id":"136","parentid":"4","topic":"随机调整","expanded":false},
|
||||
{"id":"5","parentid":"73","topic":"数论,数学","direction":"right","expanded":false},
|
||||
{"id":"72","parentid":"5","topic":"整数研究","expanded":false},
|
||||
{"id":"239","parentid":"72","topic":"素数判断,质数,筛法"},
|
||||
{"id":"241","parentid":"72","topic":"最大公约数,gcd"},
|
||||
{"id":"242","parentid":"72","topic":"扩展欧几里德,扩欧"},
|
||||
{"id":"243","parentid":"72","topic":"不定方程"},
|
||||
{"id":"244","parentid":"72","topic":"进制"},
|
||||
{"id":"250","parentid":"72","topic":"同余,中国剩余定理"},
|
||||
{"id":"251","parentid":"72","topic":"莫比乌斯反演"},
|
||||
{"id":"276","parentid":"72","topic":"逆元"},
|
||||
{"id":"245","parentid":"5","topic":"集合论","expanded":false},
|
||||
{"id":"246","parentid":"5","topic":"群论","expanded":false},
|
||||
{"id":"247","parentid":"246","topic":"置换"},
|
||||
{"id":"248","parentid":"246","topic":"Polya原理"},
|
||||
{"id":"252","parentid":"5","topic":"组合数学","expanded":false},
|
||||
{"id":"253","parentid":"252","topic":"排列组合"},
|
||||
{"id":"255","parentid":"252","topic":"二项式定理"},
|
||||
{"id":"256","parentid":"252","topic":"康托展开"},
|
||||
{"id":"257","parentid":"252","topic":"袋与球问题"},
|
||||
{"id":"258","parentid":"252","topic":"鸽笼"},
|
||||
{"id":"259","parentid":"252","topic":"容斥"},
|
||||
{"id":"260","parentid":"252","topic":"斐波那契,Fibonacci"},
|
||||
{"id":"261","parentid":"252","topic":"卡特兰,Catalan"},
|
||||
{"id":"262","parentid":"252","topic":"Stirling"},
|
||||
{"id":"264","parentid":"252","topic":"生成函数"},
|
||||
{"id":"322","parentid":"252","topic":"卢卡斯,Lucas"},
|
||||
{"id":"265","parentid":"5","topic":"线性规划","expanded":false},
|
||||
{"id":"266","parentid":"5","topic":"概率论,统计","expanded":false},
|
||||
{"id":"240","parentid":"266","topic":"众数"},
|
||||
{"id":"267","parentid":"266","topic":"简单概率"},
|
||||
{"id":"268","parentid":"266","topic":"条件概率"},
|
||||
{"id":"269","parentid":"266","topic":"Bayes"},
|
||||
{"id":"270","parentid":"266","topic":"期望"},
|
||||
{"id":"271","parentid":"5","topic":"线性代数","expanded":false},
|
||||
{"id":"71","parentid":"271","topic":"矩阵运算"},
|
||||
{"id":"272","parentid":"271","topic":"矩阵乘法"},
|
||||
{"id":"273","parentid":"271","topic":"线性递推,递推式"},
|
||||
{"id":"274","parentid":"271","topic":"高斯消元"},
|
||||
{"id":"275","parentid":"271","topic":"异或方程组"},
|
||||
{"id":"277","parentid":"271","topic":"线性基"},
|
||||
{"id":"278","parentid":"5","topic":"微积分初步","expanded":false},
|
||||
{"id":"279","parentid":"278","topic":"极限"},
|
||||
{"id":"280","parentid":"278","topic":"导数"},
|
||||
{"id":"281","parentid":"278","topic":"积分"},
|
||||
{"id":"282","parentid":"278","topic":"定积分"},
|
||||
{"id":"283","parentid":"278","topic":"立体解析几何"},
|
||||
{"id":"284","parentid":"278","topic":"级数"},
|
||||
{"id":"6","parentid":"73","topic":"图论","direction":"right","expanded":false},
|
||||
{"id":"155","parentid":"6","topic":"图的建立,建图","expanded":false},
|
||||
{"id":"156","parentid":"155","topic":"邻接矩阵"},
|
||||
{"id":"157","parentid":"155","topic":"邻接表"},
|
||||
{"id":"158","parentid":"6","topic":"图遍历","expanded":false},
|
||||
{"id":"159","parentid":"6","topic":"拓扑排序","expanded":false},
|
||||
{"id":"183","parentid":"159","topic":"AOV"},
|
||||
{"id":"184","parentid":"159","topic":"AOE"},
|
||||
{"id":"160","parentid":"6","topic":"最短路","expanded":false},
|
||||
{"id":"161","parentid":"160","topic":"Floyd"},
|
||||
{"id":"162","parentid":"160","topic":"Dijkstra"},
|
||||
{"id":"163","parentid":"160","topic":"Bellman-Ford"},
|
||||
{"id":"164","parentid":"160","topic":"SPFA"},
|
||||
{"id":"165","parentid":"160","topic":"K短路"},
|
||||
{"id":"185","parentid":"160","topic":"差分约束"},
|
||||
{"id":"166","parentid":"6","topic":"生成树","expanded":false},
|
||||
{"id":"167","parentid":"166","topic":"Prim"},
|
||||
{"id":"168","parentid":"166","topic":"Kruskal"},
|
||||
{"id":"169","parentid":"166","topic":"生成树的另类算法"},
|
||||
{"id":"170","parentid":"166","topic":"次小生成树"},
|
||||
{"id":"171","parentid":"166","topic":"特殊生成树"},
|
||||
{"id":"172","parentid":"6","topic":"圈和块","expanded":false},
|
||||
{"id":"173","parentid":"172","topic":"最小环"},
|
||||
{"id":"174","parentid":"172","topic":"负权环"},
|
||||
{"id":"175","parentid":"172","topic":"连通块"},
|
||||
{"id":"176","parentid":"172","topic":"2-SAT"},
|
||||
{"id":"177","parentid":"172","topic":"欧拉公式"},
|
||||
{"id":"178","parentid":"172","topic":"四色定理"},
|
||||
{"id":"182","parentid":"172","topic":"欧拉回路"},
|
||||
{"id":"179","parentid":"6","topic":"强连通分量,缩点","expanded":false},
|
||||
{"id":"180","parentid":"179","topic":"Tarjan"},
|
||||
{"id":"181","parentid":"179","topic":"割点"},
|
||||
{"id":"186","parentid":"6","topic":"仙人掌","expanded":false},
|
||||
{"id":"8","parentid":"73","topic":"计算几何","direction":"right","expanded":false},
|
||||
{"id":"291","parentid":"8","topic":"凸包","expanded":false},
|
||||
{"id":"292","parentid":"8","topic":"叉积","expanded":false},
|
||||
{"id":"293","parentid":"8","topic":"线段相交","expanded":false},
|
||||
{"id":"294","parentid":"8","topic":"点积","expanded":false},
|
||||
{"id":"295","parentid":"8","topic":"半平面相交,半平面交","expanded":false},
|
||||
{"id":"296","parentid":"8","topic":"最近点对","expanded":false},
|
||||
{"id":"297","parentid":"8","topic":"凸多边形的交","expanded":false},
|
||||
{"id":"298","parentid":"8","topic":"离散化扫描","expanded":false},
|
||||
{"id":"299","parentid":"8","topic":"旋转卡壳","expanded":false},
|
||||
{"id":"11","parentid":"73","topic":"树形结构","direction":"right","expanded":false},
|
||||
{"id":"42","parentid":"11","topic":"线段树","expanded":false},
|
||||
{"id":"224","parentid":"42","topic":"二维线段树"},
|
||||
{"id":"225","parentid":"42","topic":"矩形树"},
|
||||
{"id":"226","parentid":"42","topic":"zkw线段树"},
|
||||
{"id":"233","parentid":"42","topic":"主席树"},
|
||||
{"id":"49","parentid":"11","topic":"点分治","expanded":false},
|
||||
{"id":"50","parentid":"11","topic":"平衡树","expanded":false},
|
||||
{"id":"218","parentid":"50","topic":"AVL"},
|
||||
{"id":"219","parentid":"50","topic":"Treap"},
|
||||
{"id":"220","parentid":"50","topic":"SBT"},
|
||||
{"id":"221","parentid":"50","topic":"Splay"},
|
||||
{"id":"222","parentid":"50","topic":"静态排序树"},
|
||||
{"id":"223","parentid":"50","topic":"替罪羊树"},
|
||||
{"id":"51","parentid":"11","topic":"二叉堆","expanded":false},
|
||||
{"id":"215","parentid":"51","topic":"左偏树"},
|
||||
{"id":"216","parentid":"51","topic":"斜堆"},
|
||||
{"id":"217","parentid":"51","topic":"二项堆"},
|
||||
{"id":"53","parentid":"11","topic":"树状数组","expanded":false},
|
||||
{"id":"100","parentid":"11","topic":"cdq分治","expanded":false},
|
||||
{"id":"209","parentid":"11","topic":"树上距离","expanded":false},
|
||||
{"id":"210","parentid":"209","topic":"节点到根的距离"},
|
||||
{"id":"211","parentid":"209","topic":"最近公共祖先,LCA"},
|
||||
{"id":"212","parentid":"209","topic":"节点间的距离"},
|
||||
{"id":"213","parentid":"209","topic":"树的直径"},
|
||||
{"id":"227","parentid":"11","topic":"动态树","expanded":false},
|
||||
{"id":"228","parentid":"227","topic":"树链剖分,树剖"},
|
||||
{"id":"229","parentid":"227","topic":"Link-Cut Tree,LCT"},
|
||||
{"id":"230","parentid":"11","topic":"树的应用","expanded":false},
|
||||
{"id":"47","parentid":"230","topic":"并查集"},
|
||||
{"id":"208","parentid":"230","topic":"树的遍历"},
|
||||
{"id":"214","parentid":"230","topic":"哈夫曼树"},
|
||||
{"id":"231","parentid":"230","topic":"RMQ"},
|
||||
{"id":"232","parentid":"230","topic":"树套树"},
|
||||
{"id":"234","parentid":"230","topic":"可持久化"},
|
||||
{"id":"249","parentid":"230","topic":"虚树"},
|
||||
{"id":"316","parentid":"11","topic":"整体二分","expanded":false},
|
||||
{"id":"320","parentid":"11","topic":"环套树","expanded":false},
|
||||
{"id":"321","parentid":"11","topic":"K-D Tree","expanded":false},
|
||||
{"id":"44","parentid":"73","topic":"线性结构","direction":"left","expanded":false},
|
||||
{"id":"41","parentid":"44","topic":"莫队","expanded":false},
|
||||
{"id":"254","parentid":"44","topic":"前缀和","expanded":false},
|
||||
{"id":"285","parentid":"44","topic":"基本数组","expanded":false},
|
||||
{"id":"286","parentid":"44","topic":"向量","expanded":false},
|
||||
{"id":"287","parentid":"44","topic":"栈","expanded":false},
|
||||
{"id":"288","parentid":"44","topic":"队列","expanded":false},
|
||||
{"id":"289","parentid":"44","topic":"块状链表,块状数组,分块","expanded":false},
|
||||
{"id":"290","parentid":"44","topic":"st表,稀疏表","expanded":false},
|
||||
{"id":"330","parentid":"44","topic":"差分","expanded":false},
|
||||
{"id":"79","parentid":"73","topic":"网络流","direction":"left","expanded":false},
|
||||
{"id":"194","parentid":"79","topic":"最大流","expanded":false},
|
||||
{"id":"195","parentid":"194","topic":"Dinic"},
|
||||
{"id":"196","parentid":"194","topic":"Sap"},
|
||||
{"id":"197","parentid":"194","topic":"有上下界的最大流"},
|
||||
{"id":"198","parentid":"79","topic":"最小割","expanded":false},
|
||||
{"id":"199","parentid":"198","topic":"闭合图"},
|
||||
{"id":"200","parentid":"198","topic":"最小点权覆盖集"},
|
||||
{"id":"201","parentid":"198","topic":"最大点权独立集"},
|
||||
{"id":"202","parentid":"198","topic":"分数规划"},
|
||||
{"id":"203","parentid":"198","topic":"最大密度子图"},
|
||||
{"id":"204","parentid":"79","topic":"费用流","expanded":false},
|
||||
{"id":"205","parentid":"204","topic":"最短路增广费用流"},
|
||||
{"id":"206","parentid":"204","topic":"zkw费用流"},
|
||||
{"id":"207","parentid":"204","topic":"最小费用可行流"},
|
||||
{"id":"110","parentid":"73","topic":"基础算法","direction":"left","expanded":false},
|
||||
{"id":"1","parentid":"110","topic":"模拟","expanded":false},
|
||||
{"id":"7","parentid":"110","topic":"贪心","expanded":false},
|
||||
{"id":"12","parentid":"110","topic":"递推","expanded":false},
|
||||
{"id":"54","parentid":"110","topic":"递归","expanded":false},
|
||||
{"id":"111","parentid":"110","topic":"枚举,暴力","expanded":false},
|
||||
{"id":"112","parentid":"110","topic":"分治","expanded":false},
|
||||
{"id":"113","parentid":"73","topic":"排序","direction":"left","expanded":false},
|
||||
{"id":"114","parentid":"113","topic":"冒泡排序","expanded":false},
|
||||
{"id":"115","parentid":"113","topic":"选择排序","expanded":false},
|
||||
{"id":"116","parentid":"113","topic":"桶排","expanded":false},
|
||||
{"id":"117","parentid":"113","topic":"插入排序","expanded":false},
|
||||
{"id":"118","parentid":"113","topic":"归并排序","expanded":false},
|
||||
{"id":"119","parentid":"113","topic":"快速排序,快排","expanded":false},
|
||||
{"id":"120","parentid":"113","topic":"堆排序","expanded":false},
|
||||
{"id":"121","parentid":"113","topic":"希尔排序","expanded":false},
|
||||
{"id":"122","parentid":"113","topic":"外部排序","expanded":false},
|
||||
{"id":"123","parentid":"73","topic":"查找算法","direction":"left","expanded":false},
|
||||
{"id":"45","parentid":"123","topic":"二分答案","expanded":false},
|
||||
{"id":"124","parentid":"123","topic":"顺序查找","expanded":false},
|
||||
{"id":"125","parentid":"123","topic":"二分查找","expanded":false},
|
||||
{"id":"187","parentid":"73","topic":"二分图","direction":"left","expanded":false},
|
||||
{"id":"55","parentid":"187","topic":"最大匹配","expanded":false},
|
||||
{"id":"188","parentid":"55","topic":"匈牙利算法"},
|
||||
{"id":"189","parentid":"55","topic":"一般图的最大匹配"},
|
||||
{"id":"190","parentid":"55","topic":"Konig定理"},
|
||||
{"id":"191","parentid":"187","topic":"带权二分图匹配","expanded":false},
|
||||
{"id":"193","parentid":"187","topic":"稳定婚姻系统","expanded":false},
|
||||
{"id":"308","parentid":"73","topic":"其它技巧","direction":"left","expanded":false},
|
||||
{"id":"9","parentid":"308","topic":"暴力数据结构","expanded":false},
|
||||
{"id":"10","parentid":"308","topic":"高精","expanded":false},
|
||||
{"id":"13","parentid":"308","topic":"博弈论","expanded":false},
|
||||
{"id":"310","parentid":"13","topic":"Nim游戏"},
|
||||
{"id":"311","parentid":"13","topic":"博弈树"},
|
||||
{"id":"312","parentid":"13","topic":"Shannon开关游戏"},
|
||||
{"id":"43","parentid":"308","topic":"倍增","expanded":false},
|
||||
{"id":"78","parentid":"308","topic":"离散化","expanded":false},
|
||||
{"id":"235","parentid":"308","topic":"哈希,HASH","expanded":false},
|
||||
{"id":"236","parentid":"235","topic":"ELFhash"},
|
||||
{"id":"237","parentid":"235","topic":"SDBM"},
|
||||
{"id":"238","parentid":"235","topic":"BKDR"},
|
||||
{"id":"309","parentid":"308","topic":"随机贪心,随机化","expanded":false},
|
||||
{"id":"313","parentid":"308","topic":"快速傅里叶变换,DFT,FFT","expanded":false},
|
||||
{"id":"314","parentid":"308","topic":"位运算,按位","expanded":false},
|
||||
{"id":"315","parentid":"308","topic":"骗分","expanded":false},
|
||||
{"id":"317","parentid":"308","topic":"NP问题","expanded":false},
|
||||
{"id":"318","parentid":"308","topic":"构造","expanded":false},
|
||||
{"id":"324","parentid":"308","topic":"快速数论变换NTT","expanded":false},
|
||||
{"id":"326","parentid":"308","topic":"快速沃尔什变换FWT","expanded":false},
|
||||
{"id":"327","parentid":"308","topic":"快速沃尔什变换FWT","expanded":false}
|
||||
]
|
||||
};
|
||||
var options = {
|
||||
container: 'jsmind_container',
|
||||
editable: true,
|
||||
theme: 'primary'
|
||||
}
|
||||
var jm = jsMind.show(options, mind);
|
||||
jm.add_node("sub2", "sub23", "new node", {
|
||||
"background-color": "red"
|
||||
});
|
||||
jm.set_node_color('sub21', 'green', '#ccc')
|
||||
}
|
||||
load_jsmind();
|
||||
2
web/template/sidebar/js/markdown-it.min.js
vendored
Normal file
2
web/template/sidebar/js/markdown-it.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
154
web/template/sidebar/js/markdown.js
Normal file
154
web/template/sidebar/js/markdown.js
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* This file is part of moemark-renderer.
|
||||
*
|
||||
* Copyright (c) 2016 Menci <huanghaorui301@gmail.com>
|
||||
*
|
||||
* moemark-renderer is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* moemark-renderer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with moemark-renderer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const MoeMark = require('moemark');
|
||||
const katex = require('katex');
|
||||
const mj = require('mathjax-node');
|
||||
|
||||
let defaultCache = {
|
||||
data: {},
|
||||
get(key) {
|
||||
return this.data[key];
|
||||
},
|
||||
set(key, val) {
|
||||
this.data[key] = val;
|
||||
}
|
||||
};
|
||||
|
||||
let config = {
|
||||
highlight: require('./highlight')
|
||||
};
|
||||
|
||||
let uuid = require('uuid');
|
||||
|
||||
function render(s, cb) {
|
||||
if (!s.trim()) return cb('');
|
||||
|
||||
let mathCnt = 0, mathPending = 0, maths = new Array(), mathID = new Array(), hlCnt = 0, hlPending = 0, hls = new Array(), hlID = new Array(), res, callback, ss, cache = render.cache, cacheOption = render.cacheOption, finished = false;
|
||||
if (cacheOption.result) {
|
||||
let x = cache.get('RES_' + s);
|
||||
if (x !== undefined) return cb(x);
|
||||
}
|
||||
|
||||
MoeMark.setOptions({
|
||||
lineNumber: false,
|
||||
math: true,
|
||||
highlight: function(code, lang) {
|
||||
if (cacheOption.highlight) {
|
||||
let x = cache.get('H_' + lang + '_' + code);
|
||||
if (x !== undefined) return x;
|
||||
}
|
||||
let id = hlCnt;
|
||||
hlCnt++, hlPending++;
|
||||
config.highlight(code, lang, res => {
|
||||
hls[id] = res;
|
||||
if (cacheOption.highlight) cache.set('H_' + lang + '_' + code, res);
|
||||
if (!--hlPending) finish();
|
||||
});
|
||||
return hlID[id] = uuid();
|
||||
},
|
||||
mathRenderer: function(str, display) {
|
||||
let mathFinish = (error, result) => {
|
||||
if (error) maths[id] = '<p><div style="display: inline-block; border: 1px solid #000; "><strong>' + data.errors.toString() + '</strong></div></p>';
|
||||
else if (display) maths[id] = '<p style="text-align: center; ">' + result + '</p>';
|
||||
else maths[id] = result;
|
||||
if (cacheOption.math) cache.set('M_' + display + '_' + str, maths[id]);
|
||||
if (!--mathPending) finish();
|
||||
}
|
||||
|
||||
const id = mathCnt;
|
||||
mathCnt++, mathPending++;
|
||||
|
||||
try {
|
||||
let x = cache.get('M_' + display + '_' + str);
|
||||
if (x !== undefined) process.nextTick(() => mathFinish(null, x));
|
||||
else {
|
||||
let res = katex.renderToString(str, { displayMode: display });
|
||||
process.nextTick(() => mathFinish(null, '<span style="zoom: 1.01; ">' + res + '</span>'));
|
||||
}
|
||||
} catch (e) {
|
||||
mj.typeset({
|
||||
math: str,
|
||||
format: display ? 'TeX' : 'inline-TeX',
|
||||
svg: true,
|
||||
width: 0
|
||||
}, data => {
|
||||
mathFinish(data.errors, data.svg);
|
||||
});
|
||||
}
|
||||
return mathID[id] = uuid();
|
||||
}
|
||||
});
|
||||
|
||||
function finish() {
|
||||
if (finished || !res || mathPending || hlPending) return;
|
||||
finished = true;
|
||||
if (maths.length || hls.length) {
|
||||
for (let i = 0; i < maths.length; i++) {
|
||||
res = res.replace(mathID[i], maths[i]);
|
||||
}
|
||||
for (let i = 0; i < hls.length; i++) {
|
||||
res = res.replace(hlID[i], hls[i]);
|
||||
}
|
||||
}
|
||||
if (cacheOption.result) cache.set('RES_' + s, res);
|
||||
cb(res);
|
||||
}
|
||||
|
||||
try {
|
||||
let XSS = require('xss');
|
||||
let CSSFilter = require('cssfilter');
|
||||
let whiteList = Object.assign({}, require('xss/lib/default').whiteList);
|
||||
delete whiteList.audio;
|
||||
delete whiteList.video;
|
||||
for (let tag in whiteList) whiteList[tag] = whiteList[tag].concat(['style', 'class']);
|
||||
let xss = new XSS.FilterXSS({
|
||||
whiteList: whiteList,
|
||||
stripIgnoreTag: true,
|
||||
onTagAttr: (tag, name, value, isWhiteAttr) => {
|
||||
if (tag.toLowerCase() === 'img' && name.toLowerCase() === 'src' && value.startsWith('data:image/')) return name + '="' + XSS.escapeAttrValue(value) + '"';
|
||||
}
|
||||
});
|
||||
let replaceXSS = s => {
|
||||
s = xss.process(s);
|
||||
if (s) {
|
||||
s = `<div style="position: relative; overflow: hidden; ">${s}</div>`;
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
res = replaceXSS(MoeMark(s));
|
||||
if (mathPending == 0 && hlPending == 0) {
|
||||
finish();
|
||||
}
|
||||
} catch(e) {
|
||||
cb(e);
|
||||
}
|
||||
};
|
||||
|
||||
render.moemark = MoeMark;
|
||||
render.cache = defaultCache;
|
||||
render.cacheOption = {
|
||||
highlight: true,
|
||||
math: true,
|
||||
result: false
|
||||
};
|
||||
render.config = config;
|
||||
|
||||
module.exports = render;
|
||||
5
web/template/sidebar/js/respond.min.js
vendored
Normal file
5
web/template/sidebar/js/respond.min.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl
|
||||
* Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
|
||||
* */
|
||||
|
||||
!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b<s.length;b++){var c=s[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!o[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(v(c.styleSheet.rawCssText,e,f),o[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!r||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}w()};x(),c.update=x,c.getEmValue=t,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);
|
||||
1
web/template/sidebar/js/textFit.min.js
vendored
Normal file
1
web/template/sidebar/js/textFit.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
(function(root,factory){"use strict";if(typeof define==="function"&&define.amd){define([],factory)}else if(typeof exports==="object"){module.exports=factory()}else{root.textFit=factory()}})(typeof global==="object"?global:this,function(){"use strict";var defaultSettings={alignVert:false,alignHoriz:false,multiLine:false,detectMultiLine:true,minFontSize:6,maxFontSize:80,reProcess:true,widthOnly:false,alignVertWithFlexbox:false};return function textFit(els,options){if(!options)options={};var settings={};for(var key in defaultSettings){if(options.hasOwnProperty(key)){settings[key]=options[key]}else{settings[key]=defaultSettings[key]}}if(typeof els.toArray==="function"){els=els.toArray()}var elType=Object.prototype.toString.call(els);if(elType!=="[object Array]"&&elType!=="[object NodeList]"&&elType!=="[object HTMLCollection]"){els=[els]}for(var i=0;i<els.length;i++){processItem(els[i],settings)}};function processItem(el,settings){if(!isElement(el)||!settings.reProcess&&el.getAttribute("textFitted")){return false}if(!settings.reProcess){el.setAttribute("textFitted",1)}var innerSpan,originalHeight,originalHTML,originalWidth;var low,mid,high;originalHTML=el.innerHTML;originalWidth=innerWidth(el);originalHeight=innerHeight(el);if(!originalWidth||!settings.widthOnly&&!originalHeight){if(!settings.widthOnly)throw new Error("Set a static height and width on the target element "+el.outerHTML+" before using textFit!");else throw new Error("Set a static width on the target element "+el.outerHTML+" before using textFit!")}if(originalHTML.indexOf("textFitted")===-1){innerSpan=document.createElement("span");innerSpan.className="textFitted";innerSpan.style["display"]="inline-block";innerSpan.innerHTML=originalHTML;el.innerHTML="";el.appendChild(innerSpan)}else{innerSpan=el.querySelector("span.textFitted");if(hasClass(innerSpan,"textFitAlignVert")){innerSpan.className=innerSpan.className.replace("textFitAlignVert","");innerSpan.style["height"]="";el.className.replace("textFitAlignVertFlex","")}}if(settings.alignHoriz){el.style["text-align"]="center";innerSpan.style["text-align"]="center"}var multiLine=settings.multiLine;if(settings.detectMultiLine&&!multiLine&&innerSpan.scrollHeight>=parseInt(window.getComputedStyle(innerSpan)["font-size"],10)*2){multiLine=true}if(!multiLine){el.style["white-space"]="nowrap"}low=settings.minFontSize+1;high=settings.maxFontSize+1;while(low<=high){mid=parseInt((low+high)/2,10);innerSpan.style.fontSize=mid+"px";if(innerSpan.scrollWidth<=originalWidth&&(settings.widthOnly||innerSpan.scrollHeight<=originalHeight)){low=mid+1}else{high=mid-1}}innerSpan.style.fontSize=mid-1+"px";if(settings.alignVert){addStyleSheet();var height=innerSpan.scrollHeight;if(window.getComputedStyle(el)["position"]==="static"){el.style["position"]="relative"}if(!hasClass(innerSpan,"textFitAlignVert")){innerSpan.className=innerSpan.className+" textFitAlignVert"}innerSpan.style["height"]=height+"px";if(settings.alignVertWithFlexbox&&!hasClass(el,"textFitAlignVertFlex")){el.className=el.className+" textFitAlignVertFlex"}}}function innerHeight(el){var style=window.getComputedStyle(el,null);return el.clientHeight-parseInt(style.getPropertyValue("padding-top"),10)-parseInt(style.getPropertyValue("padding-bottom"),10)}function innerWidth(el){var style=window.getComputedStyle(el,null);return el.clientWidth-parseInt(style.getPropertyValue("padding-left"),10)-parseInt(style.getPropertyValue("padding-right"),10)}function isElement(o){return typeof HTMLElement==="object"?o instanceof HTMLElement:o&&typeof o==="object"&&o!==null&&o.nodeType===1&&typeof o.nodeName==="string"}function hasClass(element,cls){return(" "+element.className+" ").indexOf(" "+cls+" ")>-1}function addStyleSheet(){if(document.getElementById("textFitStyleSheet"))return;var style=[".textFitAlignVert{","position: absolute;","top: 0; right: 0; bottom: 0; left: 0;","margin: auto;","display: flex;","justify-content: center;","flex-direction: column;","}",".textFitAlignVertFlex{","display: flex;","}",".textFitAlignVertFlex .textFitAlignVert{","position: static;","}"].join("");var css=document.createElement("style");css.type="text/css";css.id="textFitStyleSheet";css.innerHTML=style;document.body.appendChild(css)}});
|
||||
292
web/template/sidebar/js/utility.js
Normal file
292
web/template/sidebar/js/utility.js
Normal file
@@ -0,0 +1,292 @@
|
||||
Array.prototype.forEachAsync = Array.prototype.mapAsync = async function (fn) {
|
||||
return Promise.all(this.map(fn));
|
||||
};
|
||||
|
||||
Array.prototype.filterAsync = async function (fn) {
|
||||
let a = await this.mapAsync(fn);
|
||||
return this.filter((x, i) => a[i]);
|
||||
};
|
||||
|
||||
global.ErrorMessage = class ErrorMessage {
|
||||
constructor(message, nextUrls, details) {
|
||||
this.message = message;
|
||||
this.nextUrls = nextUrls || {};
|
||||
this.details = details;
|
||||
}
|
||||
};
|
||||
|
||||
let Promise = require('bluebird');
|
||||
let path = require('path');
|
||||
let fs = Promise.promisifyAll(require('fs-extra'));
|
||||
let util = require('util');
|
||||
let markdownRenderer = require('./libs/markdown');
|
||||
let moment = require('moment');
|
||||
let url = require('url');
|
||||
let querystring = require('querystring');
|
||||
let gravatar = require('gravatar');
|
||||
let filesize = require('file-size');
|
||||
let AsyncLock = require('async-lock');
|
||||
|
||||
module.exports = {
|
||||
resolvePath(s) {
|
||||
let a = Array.from(arguments);
|
||||
a.unshift(__dirname);
|
||||
return path.resolve.apply(null, a);
|
||||
},
|
||||
markdown(obj, keys, noReplaceUI) {
|
||||
let replaceUI = s => {
|
||||
if (noReplaceUI) return s;
|
||||
|
||||
s = s.split('<pre>').join('<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; ">').split('</pre>').join('</pre></div>')
|
||||
.split('<table>').join('<table class="ui celled table">')
|
||||
.split('<blockquote>').join('<div class="ui message">').split('</blockquote>').join('</div>');
|
||||
|
||||
let cheerio = require('cheerio');
|
||||
let $ = cheerio.load('<html><head></head><body></body></html>');
|
||||
let body = $('body');
|
||||
body.html(s);
|
||||
|
||||
let a = $('img:only-child');
|
||||
for (let img of Array.from(a)) {
|
||||
if (!img.prev && !img.next) {
|
||||
$(img).css('display', 'block');
|
||||
$(img).css('margin', '0 auto');
|
||||
}
|
||||
}
|
||||
|
||||
return body.html();
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!keys) {
|
||||
if (!obj || !obj.trim()) resolve("");
|
||||
else markdownRenderer(obj, s => {
|
||||
resolve(replaceUI(s));
|
||||
});
|
||||
} else {
|
||||
let res = obj, cnt = keys.length;
|
||||
for (let key of keys) {
|
||||
markdownRenderer(res[key], (s) => {
|
||||
res[key] = replaceUI(s);
|
||||
if (!--cnt) resolve(res);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
formatDate(ts, format) {
|
||||
if (ts == null) {
|
||||
return "Unknown";
|
||||
}
|
||||
let m = moment(ts * 1000);
|
||||
m.locale('eu');
|
||||
return m.format(format || 'L H:mm:ss');
|
||||
},
|
||||
formatTime(x) {
|
||||
let sgn = x < 0 ? '-' : '';
|
||||
x = Math.abs(x);
|
||||
function toStringWithPad(x) {
|
||||
x = parseInt(x);
|
||||
if (x < 10) return '0' + x.toString();
|
||||
else return x.toString();
|
||||
}
|
||||
return sgn + util.format('%s:%s:%s', toStringWithPad(x / 3600), toStringWithPad(x / 60 % 60), toStringWithPad(x % 60));
|
||||
},
|
||||
formatSize(x, precision) {
|
||||
let res = filesize(x, { fixed: precision || 1 }).calculate();
|
||||
if (res.result === parseInt(res.result)) res.fixed = res.result.toString();
|
||||
if (res.suffix.startsWith('Byte')) res.suffix = 'B';
|
||||
else res.suffix = res.suffix.replace('iB', '');
|
||||
return res.fixed + ' ' + res.suffix;
|
||||
},
|
||||
judgeServer(suffix) {
|
||||
return JSON.stringify(url.resolve(syzoj.config.judge_server_addr, suffix));
|
||||
},
|
||||
parseDate(s) {
|
||||
return parseInt(+new Date(s) / 1000);
|
||||
},
|
||||
getCurrentDate(removeTime) {
|
||||
let d = new Date;
|
||||
if (removeTime) {
|
||||
d.setHours(0);
|
||||
d.setMinutes(0);
|
||||
d.setSeconds(0);
|
||||
d.setMilliseconds(0);
|
||||
}
|
||||
return parseInt(+d / 1000);
|
||||
},
|
||||
makeUrl(req_params, form) {
|
||||
let res = '';
|
||||
if (!req_params) res = '/';
|
||||
else if (req_params.originalUrl) {
|
||||
let u = url.parse(req_params.originalUrl);
|
||||
res = u.pathname;
|
||||
} else {
|
||||
if (!Array.isArray(req_params)) req_params = [req_params];
|
||||
for (let param of req_params) res += '/' + param;
|
||||
}
|
||||
let encoded = querystring.encode(form);
|
||||
if (encoded) res += '?' + encoded;
|
||||
return res;
|
||||
},
|
||||
highlight(code, lang) {
|
||||
return new Promise((resolve, reject) => {
|
||||
require('./libs/highlight')(code, lang, res => {
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
},
|
||||
gravatar(email, size) {
|
||||
return gravatar.url(email, { s: size, d: 'mm' }).replace('www.gravatar.com', 'gravatar.loli.net');
|
||||
},
|
||||
async parseTestdata(dir, submitAnswer) {
|
||||
if (!await syzoj.utils.isDir(dir)) return null;
|
||||
|
||||
try {
|
||||
// Get list of *files*
|
||||
let list = await (await fs.readdirAsync(dir)).filterAsync(async x => await syzoj.utils.isFile(path.join(dir, x)));
|
||||
|
||||
let res = [];
|
||||
if (!list.includes('data.yml')) {
|
||||
res[0] = {};
|
||||
res[0].cases = [];
|
||||
for (let file of list) {
|
||||
let parsedName = path.parse(file);
|
||||
if (parsedName.ext === '.in') {
|
||||
if (list.includes(`${parsedName.name}.out`)) {
|
||||
let o = {
|
||||
input: file,
|
||||
output: `${parsedName.name}.out`
|
||||
};
|
||||
if (submitAnswer) o.answer = `${parsedName.name}.out`;
|
||||
res[0].cases.push(o);
|
||||
}
|
||||
|
||||
if (list.includes(`${parsedName.name}.ans`)) {
|
||||
let o = {
|
||||
input: file,
|
||||
output: `${parsedName.name}.ans`
|
||||
};
|
||||
if (submitAnswer) o.answer = `${parsedName.name}.out`;
|
||||
res[0].cases.push(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res[0].type = 'sum';
|
||||
res[0].score = 100;
|
||||
res[0].cases.forEach((e) => { e.key = (e.input.match(/\d+/g) || []).map((x) => parseInt(x)).concat(e.input); });
|
||||
res[0].cases.sort((a, b) => {
|
||||
for (let i = 0; i < Math.max(a.key.length, b.key.length); ++i) {
|
||||
if (a.key[i] == undefined) return -1;
|
||||
if (b.key[i] == undefined) return +1;
|
||||
if (a.key[i] !== b.key[i]) return (a.key[i] < b.key[i] ? -1 : +1);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
res.spj = list.some(s => s.startsWith('spj_'));
|
||||
} else {
|
||||
let config = require('js-yaml').load((await fs.readFileAsync(dir + '/data.yml')));
|
||||
|
||||
let input = config.inputFile, output = config.outputFile, answer = config.userOutput;
|
||||
|
||||
res = config.subtasks.map(st => ({
|
||||
score: st.score,
|
||||
type: st.type,
|
||||
cases: st.cases.map(c => {
|
||||
function getFileName(template, id, mustExist) {
|
||||
let s = template.split('#').join(String(id));
|
||||
if (mustExist && !list.includes(s)) throw `找不到文件 ${s}`;
|
||||
return s;
|
||||
}
|
||||
|
||||
let o = {};
|
||||
if (input) o.input = getFileName(input, c, true);
|
||||
if (output) o.output = getFileName(output, c, true);
|
||||
if (answer) o.answer = getFileName(answer, c, false);
|
||||
|
||||
return o;
|
||||
})
|
||||
}));
|
||||
|
||||
res = res.filter(x => x.cases && x.cases.length !== 0);
|
||||
|
||||
res.spj = !!config.specialJudge;
|
||||
}
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return { error: e };
|
||||
}
|
||||
},
|
||||
ansiToHTML(s) {
|
||||
let Convert = require('ansi-to-html');
|
||||
let convert = new Convert({ escapeXML: true });
|
||||
return convert.toHtml(s);
|
||||
},
|
||||
paginate(count, currPage, perPage) {
|
||||
currPage = parseInt(currPage);
|
||||
if (!currPage || currPage < 1) currPage = 1;
|
||||
|
||||
let pageCnt = Math.ceil(count / perPage);
|
||||
if (currPage > pageCnt) currPage = pageCnt;
|
||||
|
||||
return {
|
||||
currPage: currPage,
|
||||
perPage: perPage,
|
||||
pageCnt: pageCnt,
|
||||
toSQL: () => {
|
||||
if (!pageCnt) return '';
|
||||
else return ` LIMIT ${(currPage - 1) * perPage},${perPage}`
|
||||
}
|
||||
};
|
||||
},
|
||||
removeTitleTag(s) {
|
||||
return s.replace(/「[\S\s]+?」/, '');
|
||||
},
|
||||
md5(data) {
|
||||
let crypto = require('crypto');
|
||||
let md5 = crypto.createHash('md5');
|
||||
md5.update(data);
|
||||
return md5.digest('hex');
|
||||
},
|
||||
isValidUsername(s) {
|
||||
return /^[a-zA-Z0-9\-\_]+$/.test(s);
|
||||
},
|
||||
locks: [],
|
||||
lock(key, cb) {
|
||||
let s = JSON.stringify(key);
|
||||
if (!this.locks[s]) this.locks[s] = new AsyncLock();
|
||||
return this.locks[s].acquire(s, cb);
|
||||
},
|
||||
encrypt(buffer, password) {
|
||||
if (typeof buffer === 'string') buffer = Buffer.from(buffer);
|
||||
let crypto = require('crypto');
|
||||
let cipher = crypto.createCipher('aes-256-ctr', password);
|
||||
return Buffer.concat([cipher.update(buffer), cipher.final()]);
|
||||
},
|
||||
decrypt(buffer, password) {
|
||||
let crypto = require('crypto');
|
||||
let decipher = crypto.createDecipher('aes-256-ctr', password);
|
||||
return Buffer.concat([decipher.update(buffer), decipher.final()]);
|
||||
},
|
||||
async isFile(path) {
|
||||
try {
|
||||
return (await fs.statAsync(path)).isFile();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
async isDir(path) {
|
||||
try {
|
||||
return (await fs.statAsync(path)).isDirectory();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
async saveConfig() {
|
||||
let fs = require('fs-extra');
|
||||
fs.writeFileAsync(syzoj.configDir, JSON.stringify(syzoj.config, null, 2));
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user