├── .gitignore ├── LICENSE ├── README.md ├── bin ├── www └── yuyu ├── package-lock.json ├── package.json ├── script ├── app.js ├── cmd.js ├── global.js ├── local.js ├── render │ ├── index.js │ ├── interface.js │ ├── modules │ │ ├── marked.js │ │ └── markex.js │ ├── render.js │ ├── type │ │ ├── file.js │ │ ├── folder.js │ │ ├── markdown.js │ │ └── todolist.js │ ├── types.js │ └── utils.js ├── router.js ├── routes │ ├── editor.js │ ├── index.js │ └── middleware │ │ └── page.js ├── spider.js ├── spider │ ├── index.js │ ├── methods │ │ └── yhx12243.js │ └── turndown.js └── www.js ├── static ├── css │ ├── archive.less │ ├── article.less │ ├── editor.less │ ├── markdown.less │ ├── pagination.less │ ├── style.less │ └── todolist.less ├── js │ ├── editor.js │ ├── modules │ │ └── readmode.js │ ├── pagination.js │ └── ui.js └── lib │ ├── highlight │ ├── default.css │ ├── highlight.min.js │ └── tomorrow.css │ ├── jquery.min.js │ ├── js.cookie.min.js │ ├── katex │ ├── fonts │ │ ├── KaTeX_AMS-Regular.ttf │ │ ├── KaTeX_AMS-Regular.woff │ │ ├── KaTeX_AMS-Regular.woff2 │ │ ├── KaTeX_Caligraphic-Bold.ttf │ │ ├── KaTeX_Caligraphic-Bold.woff │ │ ├── KaTeX_Caligraphic-Bold.woff2 │ │ ├── KaTeX_Caligraphic-Regular.ttf │ │ ├── KaTeX_Caligraphic-Regular.woff │ │ ├── KaTeX_Caligraphic-Regular.woff2 │ │ ├── KaTeX_Fraktur-Bold.ttf │ │ ├── KaTeX_Fraktur-Bold.woff │ │ ├── KaTeX_Fraktur-Bold.woff2 │ │ ├── KaTeX_Fraktur-Regular.ttf │ │ ├── KaTeX_Fraktur-Regular.woff │ │ ├── KaTeX_Fraktur-Regular.woff2 │ │ ├── KaTeX_Main-Bold.ttf │ │ ├── KaTeX_Main-Bold.woff │ │ ├── KaTeX_Main-Bold.woff2 │ │ ├── KaTeX_Main-BoldItalic.ttf │ │ ├── KaTeX_Main-BoldItalic.woff │ │ ├── KaTeX_Main-BoldItalic.woff2 │ │ ├── KaTeX_Main-Italic.ttf │ │ ├── KaTeX_Main-Italic.woff │ │ ├── KaTeX_Main-Italic.woff2 │ │ ├── KaTeX_Main-Regular.ttf │ │ ├── KaTeX_Main-Regular.woff │ │ ├── KaTeX_Main-Regular.woff2 │ │ ├── KaTeX_Math-BoldItalic.ttf │ │ ├── KaTeX_Math-BoldItalic.woff │ │ ├── KaTeX_Math-BoldItalic.woff2 │ │ ├── KaTeX_Math-Italic.ttf │ │ ├── KaTeX_Math-Italic.woff │ │ ├── KaTeX_Math-Italic.woff2 │ │ ├── KaTeX_SansSerif-Bold.ttf │ │ ├── KaTeX_SansSerif-Bold.woff │ │ ├── KaTeX_SansSerif-Bold.woff2 │ │ ├── KaTeX_SansSerif-Italic.ttf │ │ ├── KaTeX_SansSerif-Italic.woff │ │ ├── KaTeX_SansSerif-Italic.woff2 │ │ ├── KaTeX_SansSerif-Regular.ttf │ │ ├── KaTeX_SansSerif-Regular.woff │ │ ├── KaTeX_SansSerif-Regular.woff2 │ │ ├── KaTeX_Script-Regular.ttf │ │ ├── KaTeX_Script-Regular.woff │ │ ├── KaTeX_Script-Regular.woff2 │ │ ├── KaTeX_Size1-Regular.ttf │ │ ├── KaTeX_Size1-Regular.woff │ │ ├── KaTeX_Size1-Regular.woff2 │ │ ├── KaTeX_Size2-Regular.ttf │ │ ├── KaTeX_Size2-Regular.woff │ │ ├── KaTeX_Size2-Regular.woff2 │ │ ├── KaTeX_Size3-Regular.ttf │ │ ├── KaTeX_Size3-Regular.woff │ │ ├── KaTeX_Size3-Regular.woff2 │ │ ├── KaTeX_Size4-Regular.ttf │ │ ├── KaTeX_Size4-Regular.woff │ │ ├── KaTeX_Size4-Regular.woff2 │ │ ├── KaTeX_Typewriter-Regular.ttf │ │ ├── KaTeX_Typewriter-Regular.woff │ │ └── KaTeX_Typewriter-Regular.woff2 │ └── katex.min.css │ ├── monaco-editor │ └── vs │ │ ├── base │ │ ├── browser │ │ │ └── ui │ │ │ │ └── codicons │ │ │ │ └── codicon │ │ │ │ └── codicon.ttf │ │ └── worker │ │ │ └── workerMain.js │ │ ├── basic-languages │ │ ├── bat │ │ │ └── bat.js │ │ ├── cpp │ │ │ └── cpp.js │ │ ├── csharp │ │ │ └── csharp.js │ │ ├── csp │ │ │ └── csp.js │ │ ├── css │ │ │ └── css.js │ │ ├── dart │ │ │ └── dart.js │ │ ├── dockerfile │ │ │ └── dockerfile.js │ │ ├── go │ │ │ └── go.js │ │ ├── graphql │ │ │ └── graphql.js │ │ ├── handlebars │ │ │ └── handlebars.js │ │ ├── hcl │ │ │ └── hcl.js │ │ ├── html │ │ │ └── html.js │ │ ├── ini │ │ │ └── ini.js │ │ ├── java │ │ │ └── java.js │ │ ├── javascript │ │ │ └── javascript.js │ │ ├── kotlin │ │ │ └── kotlin.js │ │ ├── less │ │ │ └── less.js │ │ ├── lua │ │ │ └── lua.js │ │ ├── markdown │ │ │ └── markdown.js │ │ ├── msdax │ │ │ └── msdax.js │ │ ├── mysql │ │ │ └── mysql.js │ │ ├── objective-c │ │ │ └── objective-c.js │ │ ├── pascal │ │ │ └── pascal.js │ │ ├── perl │ │ │ └── perl.js │ │ ├── php │ │ │ └── php.js │ │ ├── powershell │ │ │ └── powershell.js │ │ ├── python │ │ │ └── python.js │ │ ├── r │ │ │ └── r.js │ │ ├── razor │ │ │ └── razor.js │ │ ├── redis │ │ │ └── redis.js │ │ ├── redshift │ │ │ └── redshift.js │ │ ├── restructuredtext │ │ │ └── restructuredtext.js │ │ ├── ruby │ │ │ └── ruby.js │ │ ├── rust │ │ │ └── rust.js │ │ ├── sb │ │ │ └── sb.js │ │ ├── scala │ │ │ └── scala.js │ │ ├── scheme │ │ │ └── scheme.js │ │ ├── scss │ │ │ └── scss.js │ │ ├── shell │ │ │ └── shell.js │ │ ├── solidity │ │ │ └── solidity.js │ │ ├── sophia │ │ │ └── sophia.js │ │ ├── sql │ │ │ └── sql.js │ │ ├── st │ │ │ └── st.js │ │ ├── swift │ │ │ └── swift.js │ │ ├── systemverilog │ │ │ └── systemverilog.js │ │ ├── tcl │ │ │ └── tcl.js │ │ ├── twig │ │ │ └── twig.js │ │ ├── typescript │ │ │ └── typescript.js │ │ ├── vb │ │ │ └── vb.js │ │ ├── xml │ │ │ └── xml.js │ │ └── yaml │ │ │ └── yaml.js │ │ ├── editor │ │ ├── editor.main.css │ │ ├── editor.main.js │ │ ├── editor.main.nls.de.js │ │ ├── editor.main.nls.es.js │ │ ├── editor.main.nls.fr.js │ │ ├── editor.main.nls.it.js │ │ ├── editor.main.nls.ja.js │ │ ├── editor.main.nls.js │ │ ├── editor.main.nls.ko.js │ │ ├── editor.main.nls.ru.js │ │ ├── editor.main.nls.zh-cn.js │ │ └── editor.main.nls.zh-tw.js │ │ ├── language │ │ ├── css │ │ │ ├── cssMode.js │ │ │ └── cssWorker.js │ │ ├── html │ │ │ ├── htmlMode.js │ │ │ └── htmlWorker.js │ │ ├── json │ │ │ ├── jsonMode.js │ │ │ └── jsonWorker.js │ │ └── typescript │ │ │ ├── tsMode.js │ │ │ └── tsWorker.js │ │ └── loader.js │ ├── pdfjs │ ├── build │ │ ├── pdf.js │ │ ├── pdf.js.map │ │ ├── pdf.worker.js │ │ └── pdf.worker.js.map │ └── web │ │ ├── cmaps │ │ ├── 78-EUC-H.bcmap │ │ ├── 78-EUC-V.bcmap │ │ ├── 78-H.bcmap │ │ ├── 78-RKSJ-H.bcmap │ │ ├── 78-RKSJ-V.bcmap │ │ ├── 78-V.bcmap │ │ ├── 78ms-RKSJ-H.bcmap │ │ ├── 78ms-RKSJ-V.bcmap │ │ ├── 83pv-RKSJ-H.bcmap │ │ ├── 90ms-RKSJ-H.bcmap │ │ ├── 90ms-RKSJ-V.bcmap │ │ ├── 90msp-RKSJ-H.bcmap │ │ ├── 90msp-RKSJ-V.bcmap │ │ ├── 90pv-RKSJ-H.bcmap │ │ ├── 90pv-RKSJ-V.bcmap │ │ ├── Add-H.bcmap │ │ ├── Add-RKSJ-H.bcmap │ │ ├── Add-RKSJ-V.bcmap │ │ ├── Add-V.bcmap │ │ ├── Adobe-CNS1-0.bcmap │ │ ├── Adobe-CNS1-1.bcmap │ │ ├── Adobe-CNS1-2.bcmap │ │ ├── Adobe-CNS1-3.bcmap │ │ ├── Adobe-CNS1-4.bcmap │ │ ├── Adobe-CNS1-5.bcmap │ │ ├── Adobe-CNS1-6.bcmap │ │ ├── Adobe-CNS1-UCS2.bcmap │ │ ├── Adobe-GB1-0.bcmap │ │ ├── Adobe-GB1-1.bcmap │ │ ├── Adobe-GB1-2.bcmap │ │ ├── Adobe-GB1-3.bcmap │ │ ├── Adobe-GB1-4.bcmap │ │ ├── Adobe-GB1-5.bcmap │ │ ├── Adobe-GB1-UCS2.bcmap │ │ ├── Adobe-Japan1-0.bcmap │ │ ├── Adobe-Japan1-1.bcmap │ │ ├── Adobe-Japan1-2.bcmap │ │ ├── Adobe-Japan1-3.bcmap │ │ ├── Adobe-Japan1-4.bcmap │ │ ├── Adobe-Japan1-5.bcmap │ │ ├── Adobe-Japan1-6.bcmap │ │ ├── Adobe-Japan1-UCS2.bcmap │ │ ├── Adobe-Korea1-0.bcmap │ │ ├── Adobe-Korea1-1.bcmap │ │ ├── Adobe-Korea1-2.bcmap │ │ ├── Adobe-Korea1-UCS2.bcmap │ │ ├── B5-H.bcmap │ │ ├── B5-V.bcmap │ │ ├── B5pc-H.bcmap │ │ ├── B5pc-V.bcmap │ │ ├── CNS-EUC-H.bcmap │ │ ├── CNS-EUC-V.bcmap │ │ ├── CNS1-H.bcmap │ │ ├── CNS1-V.bcmap │ │ ├── CNS2-H.bcmap │ │ ├── CNS2-V.bcmap │ │ ├── ETHK-B5-H.bcmap │ │ ├── ETHK-B5-V.bcmap │ │ ├── ETen-B5-H.bcmap │ │ ├── ETen-B5-V.bcmap │ │ ├── ETenms-B5-H.bcmap │ │ ├── ETenms-B5-V.bcmap │ │ ├── EUC-H.bcmap │ │ ├── EUC-V.bcmap │ │ ├── Ext-H.bcmap │ │ ├── Ext-RKSJ-H.bcmap │ │ ├── Ext-RKSJ-V.bcmap │ │ ├── Ext-V.bcmap │ │ ├── GB-EUC-H.bcmap │ │ ├── GB-EUC-V.bcmap │ │ ├── GB-H.bcmap │ │ ├── GB-V.bcmap │ │ ├── GBK-EUC-H.bcmap │ │ ├── GBK-EUC-V.bcmap │ │ ├── GBK2K-H.bcmap │ │ ├── GBK2K-V.bcmap │ │ ├── GBKp-EUC-H.bcmap │ │ ├── GBKp-EUC-V.bcmap │ │ ├── GBT-EUC-H.bcmap │ │ ├── GBT-EUC-V.bcmap │ │ ├── GBT-H.bcmap │ │ ├── GBT-V.bcmap │ │ ├── GBTpc-EUC-H.bcmap │ │ ├── GBTpc-EUC-V.bcmap │ │ ├── GBpc-EUC-H.bcmap │ │ ├── GBpc-EUC-V.bcmap │ │ ├── H.bcmap │ │ ├── HKdla-B5-H.bcmap │ │ ├── HKdla-B5-V.bcmap │ │ ├── HKdlb-B5-H.bcmap │ │ ├── HKdlb-B5-V.bcmap │ │ ├── HKgccs-B5-H.bcmap │ │ ├── HKgccs-B5-V.bcmap │ │ ├── HKm314-B5-H.bcmap │ │ ├── HKm314-B5-V.bcmap │ │ ├── HKm471-B5-H.bcmap │ │ ├── HKm471-B5-V.bcmap │ │ ├── HKscs-B5-H.bcmap │ │ ├── HKscs-B5-V.bcmap │ │ ├── Hankaku.bcmap │ │ ├── Hiragana.bcmap │ │ ├── KSC-EUC-H.bcmap │ │ ├── KSC-EUC-V.bcmap │ │ ├── KSC-H.bcmap │ │ ├── KSC-Johab-H.bcmap │ │ ├── KSC-Johab-V.bcmap │ │ ├── KSC-V.bcmap │ │ ├── KSCms-UHC-H.bcmap │ │ ├── KSCms-UHC-HW-H.bcmap │ │ ├── KSCms-UHC-HW-V.bcmap │ │ ├── KSCms-UHC-V.bcmap │ │ ├── KSCpc-EUC-H.bcmap │ │ ├── KSCpc-EUC-V.bcmap │ │ ├── Katakana.bcmap │ │ ├── LICENSE │ │ ├── NWP-H.bcmap │ │ ├── NWP-V.bcmap │ │ ├── RKSJ-H.bcmap │ │ ├── RKSJ-V.bcmap │ │ ├── Roman.bcmap │ │ ├── UniCNS-UCS2-H.bcmap │ │ ├── UniCNS-UCS2-V.bcmap │ │ ├── UniCNS-UTF16-H.bcmap │ │ ├── UniCNS-UTF16-V.bcmap │ │ ├── UniCNS-UTF32-H.bcmap │ │ ├── UniCNS-UTF32-V.bcmap │ │ ├── UniCNS-UTF8-H.bcmap │ │ ├── UniCNS-UTF8-V.bcmap │ │ ├── UniGB-UCS2-H.bcmap │ │ ├── UniGB-UCS2-V.bcmap │ │ ├── UniGB-UTF16-H.bcmap │ │ ├── UniGB-UTF16-V.bcmap │ │ ├── UniGB-UTF32-H.bcmap │ │ ├── UniGB-UTF32-V.bcmap │ │ ├── UniGB-UTF8-H.bcmap │ │ ├── UniGB-UTF8-V.bcmap │ │ ├── UniJIS-UCS2-H.bcmap │ │ ├── UniJIS-UCS2-HW-H.bcmap │ │ ├── UniJIS-UCS2-HW-V.bcmap │ │ ├── UniJIS-UCS2-V.bcmap │ │ ├── UniJIS-UTF16-H.bcmap │ │ ├── UniJIS-UTF16-V.bcmap │ │ ├── UniJIS-UTF32-H.bcmap │ │ ├── UniJIS-UTF32-V.bcmap │ │ ├── UniJIS-UTF8-H.bcmap │ │ ├── UniJIS-UTF8-V.bcmap │ │ ├── UniJIS2004-UTF16-H.bcmap │ │ ├── UniJIS2004-UTF16-V.bcmap │ │ ├── UniJIS2004-UTF32-H.bcmap │ │ ├── UniJIS2004-UTF32-V.bcmap │ │ ├── UniJIS2004-UTF8-H.bcmap │ │ ├── UniJIS2004-UTF8-V.bcmap │ │ ├── UniJISPro-UCS2-HW-V.bcmap │ │ ├── UniJISPro-UCS2-V.bcmap │ │ ├── UniJISPro-UTF8-V.bcmap │ │ ├── UniJISX0213-UTF32-H.bcmap │ │ ├── UniJISX0213-UTF32-V.bcmap │ │ ├── UniJISX02132004-UTF32-H.bcmap │ │ ├── UniJISX02132004-UTF32-V.bcmap │ │ ├── UniKS-UCS2-H.bcmap │ │ ├── UniKS-UCS2-V.bcmap │ │ ├── UniKS-UTF16-H.bcmap │ │ ├── UniKS-UTF16-V.bcmap │ │ ├── UniKS-UTF32-H.bcmap │ │ ├── UniKS-UTF32-V.bcmap │ │ ├── UniKS-UTF8-H.bcmap │ │ ├── UniKS-UTF8-V.bcmap │ │ ├── V.bcmap │ │ └── WP-Symbol.bcmap │ │ ├── debugger.js │ │ ├── images │ │ ├── annotation-check.svg │ │ ├── annotation-comment.svg │ │ ├── annotation-help.svg │ │ ├── annotation-insert.svg │ │ ├── annotation-key.svg │ │ ├── annotation-newparagraph.svg │ │ ├── annotation-noicon.svg │ │ ├── annotation-note.svg │ │ ├── annotation-paragraph.svg │ │ ├── findbarButton-next-rtl.png │ │ ├── findbarButton-next-rtl@2x.png │ │ ├── findbarButton-next.png │ │ ├── findbarButton-next@2x.png │ │ ├── findbarButton-previous-rtl.png │ │ ├── findbarButton-previous-rtl@2x.png │ │ ├── findbarButton-previous.png │ │ ├── findbarButton-previous@2x.png │ │ ├── grab.cur │ │ ├── grabbing.cur │ │ ├── loading-icon.gif │ │ ├── loading-small.png │ │ ├── loading-small@2x.png │ │ ├── secondaryToolbarButton-documentProperties.png │ │ ├── secondaryToolbarButton-documentProperties@2x.png │ │ ├── secondaryToolbarButton-firstPage.png │ │ ├── secondaryToolbarButton-firstPage@2x.png │ │ ├── secondaryToolbarButton-handTool.png │ │ ├── secondaryToolbarButton-handTool@2x.png │ │ ├── secondaryToolbarButton-lastPage.png │ │ ├── secondaryToolbarButton-lastPage@2x.png │ │ ├── secondaryToolbarButton-rotateCcw.png │ │ ├── secondaryToolbarButton-rotateCcw@2x.png │ │ ├── secondaryToolbarButton-rotateCw.png │ │ ├── secondaryToolbarButton-rotateCw@2x.png │ │ ├── secondaryToolbarButton-scrollHorizontal.png │ │ ├── secondaryToolbarButton-scrollHorizontal@2x.png │ │ ├── secondaryToolbarButton-scrollVertical.png │ │ ├── secondaryToolbarButton-scrollVertical@2x.png │ │ ├── secondaryToolbarButton-scrollWrapped.png │ │ ├── secondaryToolbarButton-scrollWrapped@2x.png │ │ ├── secondaryToolbarButton-selectTool.png │ │ ├── secondaryToolbarButton-selectTool@2x.png │ │ ├── secondaryToolbarButton-spreadEven.png │ │ ├── secondaryToolbarButton-spreadEven@2x.png │ │ ├── secondaryToolbarButton-spreadNone.png │ │ ├── secondaryToolbarButton-spreadNone@2x.png │ │ ├── secondaryToolbarButton-spreadOdd.png │ │ ├── secondaryToolbarButton-spreadOdd@2x.png │ │ ├── shadow.png │ │ ├── texture.png │ │ ├── toolbarButton-bookmark.png │ │ ├── toolbarButton-bookmark@2x.png │ │ ├── toolbarButton-download.png │ │ ├── toolbarButton-download@2x.png │ │ ├── toolbarButton-menuArrows.png │ │ ├── toolbarButton-menuArrows@2x.png │ │ ├── toolbarButton-openFile.png │ │ ├── toolbarButton-openFile@2x.png │ │ ├── toolbarButton-pageDown-rtl.png │ │ ├── toolbarButton-pageDown-rtl@2x.png │ │ ├── toolbarButton-pageDown.png │ │ ├── toolbarButton-pageDown@2x.png │ │ ├── toolbarButton-pageUp-rtl.png │ │ ├── toolbarButton-pageUp-rtl@2x.png │ │ ├── toolbarButton-pageUp.png │ │ ├── toolbarButton-pageUp@2x.png │ │ ├── toolbarButton-presentationMode.png │ │ ├── toolbarButton-presentationMode@2x.png │ │ ├── toolbarButton-print.png │ │ ├── toolbarButton-print@2x.png │ │ ├── toolbarButton-search.png │ │ ├── toolbarButton-search@2x.png │ │ ├── toolbarButton-secondaryToolbarToggle-rtl.png │ │ ├── toolbarButton-secondaryToolbarToggle-rtl@2x.png │ │ ├── toolbarButton-secondaryToolbarToggle.png │ │ ├── toolbarButton-secondaryToolbarToggle@2x.png │ │ ├── toolbarButton-sidebarToggle-rtl.png │ │ ├── toolbarButton-sidebarToggle-rtl@2x.png │ │ ├── toolbarButton-sidebarToggle.png │ │ ├── toolbarButton-sidebarToggle@2x.png │ │ ├── toolbarButton-viewAttachments.png │ │ ├── toolbarButton-viewAttachments@2x.png │ │ ├── toolbarButton-viewOutline-rtl.png │ │ ├── toolbarButton-viewOutline-rtl@2x.png │ │ ├── toolbarButton-viewOutline.png │ │ ├── toolbarButton-viewOutline@2x.png │ │ ├── toolbarButton-viewThumbnail.png │ │ ├── toolbarButton-viewThumbnail@2x.png │ │ ├── toolbarButton-zoomIn.png │ │ ├── toolbarButton-zoomIn@2x.png │ │ ├── toolbarButton-zoomOut.png │ │ ├── toolbarButton-zoomOut@2x.png │ │ ├── treeitem-collapsed-rtl.png │ │ ├── treeitem-collapsed-rtl@2x.png │ │ ├── treeitem-collapsed.png │ │ ├── treeitem-collapsed@2x.png │ │ ├── treeitem-expanded.png │ │ └── treeitem-expanded@2x.png │ │ ├── locale │ │ ├── en-US │ │ │ └── viewer.properties │ │ ├── locale.properties │ │ └── zh-CN │ │ │ └── viewer.properties │ │ ├── viewer.css │ │ ├── viewer.html │ │ ├── viewer.js │ │ └── viewer.js.map │ └── semantic │ ├── semantic.min.css │ ├── semantic.min.js │ └── themes │ └── default │ └── assets │ ├── fonts │ ├── brand-icons.eot │ ├── brand-icons.svg │ ├── brand-icons.ttf │ ├── brand-icons.woff │ ├── brand-icons.woff2 │ ├── icons.eot │ ├── icons.otf │ ├── icons.svg │ ├── icons.ttf │ ├── icons.woff │ ├── icons.woff2 │ ├── outline-icons.eot │ ├── outline-icons.svg │ ├── outline-icons.ttf │ ├── outline-icons.woff │ └── outline-icons.woff2 │ └── images │ └── flags.png └── views ├── archive.ejs ├── article.ejs ├── editor.ejs ├── error.ejs ├── footer.ejs ├── header.ejs ├── page.ejs ├── pagination.ejs ├── timeline.ejs └── todolist.ejs /.gitignore: -------------------------------------------------------------------------------- 1 | src 2 | dist 3 | config.yml 4 | static/css/*.css 5 | views/static/css/*.css 6 | views/*/static/css/*.css 7 | 8 | # Others 9 | .DS_Store 10 | 11 | # Logs 12 | logs 13 | *.log 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | lerna-debug.log* 18 | 19 | # Diagnostic reports (https://nodejs.org/api/report.html) 20 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 21 | 22 | # Runtime data 23 | pids 24 | *.pid 25 | *.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | lib-cov 30 | 31 | # Coverage directory used by tools like istanbul 32 | coverage 33 | *.lcov 34 | 35 | # nyc test coverage 36 | .nyc_output 37 | 38 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 39 | .grunt 40 | 41 | # Bower dependency directory (https://bower.io/) 42 | bower_components 43 | 44 | # node-waf configuration 45 | .lock-wscript 46 | 47 | # Compiled binary addons (https://nodejs.org/api/addons.html) 48 | build/Release 49 | 50 | # Dependency directories 51 | node_modules/ 52 | jspm_packages/ 53 | 54 | # TypeScript v1 declaration files 55 | typings/ 56 | 57 | # TypeScript cache 58 | *.tsbuildinfo 59 | 60 | # Optional npm cache directory 61 | .npm 62 | 63 | # Optional eslint cache 64 | .eslintcache 65 | 66 | # Microbundle cache 67 | .rpt2_cache/ 68 | .rts2_cache_cjs/ 69 | .rts2_cache_es/ 70 | .rts2_cache_umd/ 71 | 72 | # Optional REPL history 73 | .node_repl_history 74 | 75 | # Output of 'npm pack' 76 | *.tgz 77 | 78 | # Yarn Integrity file 79 | .yarn-integrity 80 | 81 | # dotenv environment variables file 82 | .env 83 | .env.test 84 | 85 | # parcel-bundler cache (https://parceljs.org/) 86 | .cache 87 | 88 | # Next.js build output 89 | .next 90 | 91 | # Nuxt.js build / generate output 92 | .nuxt 93 | dist 94 | 95 | # Gatsby files 96 | .cache/ 97 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 98 | # https://nextjs.org/blog/next-9-1#public-directory-support 99 | # public 100 | 101 | # vuepress build output 102 | .vuepress/dist 103 | 104 | # Serverless directories 105 | .serverless/ 106 | 107 | # FuseBox cache 108 | .fusebox/ 109 | 110 | # DynamoDB Local files 111 | .dynamodb/ 112 | 113 | # TernJS port file 114 | .tern-port 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # yuyu 2 | 3 | ### Install 4 | 5 | ```shell 6 | git clone https://github.com/memset0/yuyu 7 | cd yuyu 8 | npm install 9 | chmod +x ./bin/yuyu 10 | ln -s ./bin/yuyu /usr/local/bin 11 | ``` 12 | 13 | ### Usage 14 | 15 | ```shell 16 | yuyu server -p # 动态监听端口 17 | yuyu generate # 生成静态文件 18 | ``` 19 | 20 | 博客源文件应置于 `./src`,或 `YUYU_SOUCRE` 环境变量指向的目录下。 21 | 22 | 博文支持 ejs + Markdown + LaTeX 语法,并提供了一些预设函数,会依次进行解析。配置标题日期的方法类似于 Hexo。 23 | 24 | 本项目还附赠了一些有用的小功能,欢迎来玩(x -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/memset0/yuyu/a20d0b2aed9a819af4cbf94f34d2fb8e22b44876/bin/www -------------------------------------------------------------------------------- /bin/yuyu: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const YAML = require('yaml'); 6 | const chalk = require('chalk'); 7 | const process = require('process'); 8 | const commander = require('commander'); 9 | 10 | const source_dir = process.env['YUYU_SOURCE'] || path.join(__dirname, '../src/'); 11 | const config = YAML.parse(fs.readFileSync(path.join(source_dir, 'config.yml')).toString()); 12 | const package = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json')).toString()); 13 | const lib = { 14 | www: require('../script/www'), 15 | local: require('../script/local'), 16 | spider: require('../script/spider'), 17 | cmdtools: require('../script/cmd'), 18 | }; 19 | 20 | function log(command, dialog) { 21 | let spliter = '============================================================'; 22 | console.log( 23 | chalk.grey(spliter) + '\n' + 24 | ' ' + chalk.greenBright(`yuyu@${package.version}`) + ' -> ' + chalk.blueBright(command) + '\n' + 25 | ' ' + dialog + '\n' + 26 | chalk.grey(spliter) + '\n'); 27 | } 28 | 29 | commander.command('server') 30 | .option('-p, --port ', 'port for server') 31 | .action(function (option) { 32 | let port = option.port ? option.port : 3000; 33 | log('server', `server is running on http://localhost:${port}`); 34 | lib.www(port); 35 | }) 36 | 37 | commander.command('generate') 38 | .action(function () { 39 | log('generate', 'generate static files'); 40 | lib.local(); 41 | }) 42 | 43 | commander.command('edit ') 44 | .action(function (uri) { 45 | lib.cmdtools.edit(uri); 46 | }); 47 | 48 | commander.command('spider ') 49 | .action(async function (url) { 50 | let data = await lib.spider(url); 51 | let text = '---\n'; 52 | Object.keys(data.data).forEach(key => { 53 | let value = data.data[key].replace('\n', '\\n').replace('"', '\"').replace('\\', '\\\\'); 54 | text += key + ': "' + value + '"\n' 55 | }); 56 | text += '---\n\n' + data.text; 57 | console.log(url, data.name, data.data); 58 | fs.mkdirSync(path.join(process.cwd(), data.name), { recursive: true }); 59 | fs.writeFileSync(path.join(process.cwd(), data.name, 'index.md'), text); 60 | }); 61 | 62 | if (require.main == module) { 63 | commander.parse(process.argv); 64 | } 65 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yuyu", 3 | "version": "1.2.0", 4 | "description": "yuyu", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node ./bin/yuyu server", 8 | "server": "node ./bin/yuyu server", 9 | "generate": "node ./bin/yuyu generate" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/memset0/yuyu.git" 14 | }, 15 | "author": "", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/memset0/yuyu/issues" 19 | }, 20 | "homepage": "https://github.com/memset0/yuyu#readme", 21 | "dependencies": { 22 | "chalk": "^4.1.0", 23 | "cheerio": "^1.0.0-rc.3", 24 | "commander": "^5.1.0", 25 | "cookie-parser": "^1.4.5", 26 | "debug": "^4.1.1", 27 | "ejs": "^3.1.3", 28 | "express": "^4.17.1", 29 | "gulp": "^4.0.2", 30 | "highlight.js": "^10.1.1", 31 | "http-errors": "^1.7.3", 32 | "katex": "^0.11.1", 33 | "less-middleware": "^3.1.0", 34 | "lodash": "^4.17.19", 35 | "lru-cache": "^5.1.1", 36 | "marked": "^1.1.0", 37 | "mathjax": "^3.0.5", 38 | "mathjax-full": "^3.0.5", 39 | "md5": "^2.2.1", 40 | "moment": "^2.27.0", 41 | "morgan": "^1.10.0", 42 | "rd": "^2.0.1", 43 | "string-random": "^0.1.3", 44 | "superagent": "^5.3.1", 45 | "turndown": "^6.0.0", 46 | "xmorse": "^1.0.0", 47 | "yaml": "^1.10.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /script/app.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const YAML = require('yaml'); 4 | const express = require('express'); 5 | 6 | // register global arguments 7 | global.source_dir = process.env['YUYU_SOURCE'] || path.join(__dirname, '../src/'); 8 | global.status = 'online'; 9 | global.router = require('./router') 10 | global.config = YAML.parse(fs.readFileSync(path.join(source_dir, 'config.yml')).toString()); 11 | 12 | // express app init. 13 | const logger = require('morgan'); 14 | const cookieParser = require('cookie-parser'); 15 | const lessMiddleware = require('less-middleware'); 16 | let app = express(); 17 | app.set('views', path.join(__dirname, '../views')); 18 | app.set('view engine', 'ejs'); 19 | app.use(logger('dev')); 20 | app.use(express.json()); 21 | app.use(express.urlencoded({ extended: false })); 22 | app.use(cookieParser()); 23 | app.use(lessMiddleware(path.join(__dirname, '../static'))); 24 | app.use(express.static(path.join(__dirname, '../static'), { 25 | dotfiles: 'deny', 26 | maxAge: config.static.max_age 27 | })); 28 | 29 | // router 30 | app.use(require('./routes/middleware/page')) 31 | app.use('/', require('./routes/index')); 32 | app.use('/edit', require('./routes/editor')); 33 | 34 | // catch 404 error 35 | const createError = require('http-errors'); 36 | app.use(function (req, res, next) { 37 | next(createError(404)); 38 | }); 39 | 40 | // error handler 41 | app.use(function (err, req, res, next) { 42 | res.locals.message = err.message; 43 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 44 | 45 | res.status(err.status || 500); 46 | res.render('error'); 47 | }); 48 | 49 | module.exports = app; 50 | -------------------------------------------------------------------------------- /script/cmd.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const { exec } = require('child_process'); 4 | 5 | const router = require('./router'); 6 | const config = require('./global').config; 7 | 8 | const commandLineTools = { 9 | edit: function (uri) { 10 | if (!uri.startsWith('/')) uri = '/' + uri; 11 | if (!uri.endsWith('/')) uri = uri + '/'; 12 | 13 | if (!Object.keys(router.routes).includes(uri)) { 14 | console.log('No such uri!'); 15 | return; 16 | } 17 | 18 | let file = router.routes[uri]; 19 | exec(config.command.edit.replace(/%s/g, file.path)); 20 | } 21 | }; 22 | 23 | module.exports = commandLineTools; -------------------------------------------------------------------------------- /script/global.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const YAML = require('yaml'); 4 | 5 | const source_dir = process.env['YUYU_SOURCE'] || path.join(__dirname, '../src/'); 6 | const config = YAML.parse(fs.readFileSync(path.join(source_dir, 'config.yml')).toString()); 7 | 8 | function readYAMLFile(dir) { 9 | let text = fs.readFileSync(dir).toString(); 10 | let data = YAML.parse(text); 11 | 12 | return data; 13 | } 14 | 15 | module.exports = { 16 | config: config, 17 | 18 | fs: require('fs'), 19 | url: require('url'), 20 | path: require('path'), 21 | lodash: require('lodash'), 22 | cheerio: require('cheerio'), 23 | } -------------------------------------------------------------------------------- /script/local.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const rd = require('rd'); 3 | const ejs = require('ejs'); 4 | const path = require('path'); 5 | const YAML = require('yaml'); 6 | const chalk = require('chalk'); 7 | const { requireLanguage } = require('highlight.js'); 8 | 9 | // register global arguments 10 | global.source_dir = process.env['YUYU_SOURCE'] || path.join(__dirname, '../src/'); 11 | global.status = 'offline'; 12 | global.router = require('./router') 13 | global.config = YAML.parse(fs.readFileSync(path.join(source_dir, 'config.yml')).toString()); 14 | 15 | // static files api 16 | const static = (function () { 17 | let root = path.join(__dirname, '../static'); 18 | let api = { 19 | list: function () { 20 | return rd.readFileSync(root).map(target => ({ 21 | path: target, 22 | uri: path.join('/', path.relative(root, target)).replace(/\\/g, '/'), 23 | })); 24 | }, 25 | }; 26 | 27 | return api; 28 | })(); 29 | 30 | // dist files api 31 | const dist = (function () { 32 | let root = process.env['YUYU_DIST'] || path.join(__dirname, '../dist'); 33 | let api = { 34 | makedirs: function (target) { 35 | fs.mkdirSync(target, { recursive: true }); 36 | }, 37 | copyFileFrom: function (target, source) { 38 | target = path.join(root, target); 39 | api.makedirs(path.dirname(target)); 40 | fs.copyFileSync(source, target); 41 | }, 42 | writeFile: function (target, content) { 43 | target = path.join(root, target); 44 | api.makedirs(path.dirname(target)); 45 | fs.writeFileSync(target, content); 46 | }, 47 | }; 48 | 49 | api.makedirs(root); 50 | return api; 51 | })(); 52 | 53 | ejs.compileFile = function(filePath, options) { 54 | let templatePath = filePath; 55 | if (options && options.root) templatePath = path.resolve(options.root, templatePath); 56 | const templateStr = ejs.fileLoader(templatePath, 'utf8'); 57 | options = Object.assign({ filename: templatePath }, options); 58 | return ejs.compile(templateStr, options); 59 | } 60 | 61 | module.exports = function() { 62 | let template = {}; 63 | 64 | static.list().forEach(file => { 65 | dist.copyFileFrom(file.uri, file.path); 66 | console.log(chalk.yellow('[static file]') + ' /' + path.relative(router.root, file.path) + chalk.yellowBright(' => ') + file.uri); 67 | }); 68 | Object.values(router.routes).forEach(file => { 69 | let data = file.render(); 70 | if (data.code != 200) { 71 | console.error(chalk.red('[error' + data.code + ']') + ' ' + file.path); 72 | return; 73 | } 74 | if (data.type == 'file') { 75 | dist.copyFileFrom(file.uri, file.path); 76 | console.log(chalk.blue('[file]') + ' /' + path.relative(router.root, file.path) + chalk.yellowBright(' => ') + file.uri); 77 | } else if (data.type == 'page') { 78 | if (!template[data.res.template]) { 79 | template[data.res.template]= ejs.compileFile(path.join(__dirname, '../views/', data.res.template + '.ejs')); 80 | } 81 | dist.writeFile(file.uri + 'index.html', template[data.res.template]({ ...data.res.arguments })); 82 | console.log(chalk.green('[page]') + ' /' + path.relative(router.root, file.path) + chalk.yellowBright(' => ') + file.uri + 'index.html'); 83 | } 84 | }) 85 | } 86 | 87 | if (require.main == module) { 88 | module.exports(); 89 | } -------------------------------------------------------------------------------- /script/render/index.js: -------------------------------------------------------------------------------- 1 | const rd = require('rd'); 2 | const pt = require('path'); 3 | 4 | const File = require('./interface'); 5 | 6 | function listFiles(srcRoot) { 7 | srcRoot = pt.normalize(srcRoot); 8 | return rd.readSync(srcRoot).map(file => new File(file, { srcRoot })); 9 | } 10 | 11 | // console.log(listFiles(pt.join(__dirname, '../../src'))); 12 | 13 | // listFiles(pt.join(__dirname, '../../src')).forEach(file => { 14 | // let dist = pt.join(pt.join(__dirname, '../../dist'), file.uri); 15 | // console.log(dist); 16 | // if (file.type == 'folder') { 17 | // if (!fs.existsSync(dist)) { 18 | // fs.mkdirSync(dist); 19 | // } 20 | // } else if (file.type == 'file') { 21 | // fs.createReadStream(file.path).pipe(fs.createWriteStream(dist)); 22 | // } else if (file.type == 'markdown') { 23 | // if (!fs.existsSync(dist)) { 24 | // fs.mkdirSync(dist); 25 | // } 26 | // let rendered = file.renderMarkdown(); 27 | // fs.writeFileSync(pt.join(dist, 'index.md'), rendered.text); 28 | // } 29 | // }) 30 | 31 | module.exports = { 32 | File: File, 33 | listFiles: listFiles, 34 | } -------------------------------------------------------------------------------- /script/render/interface.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const lib = require('./types'); 3 | 4 | class File { 5 | read() { return fs.readFileSync(this.path).toString(); } 6 | readJSON() { return fs.readFileSync(this.path).toJSON(); } 7 | write(content) { return fs.writeFileSync(this.path, content); } 8 | writeJSON(content) { return fs.writeFileSync(this.path, JSON.stringify(content)); } 9 | 10 | render(options = null) { 11 | if (!lib[this.type].render) { return { code: 403 }; } 12 | if (!options) options = {}; 13 | if (options.options) options = { ...options, ...options.options }; 14 | return lib[this.type].render(this, options); 15 | } 16 | 17 | constructor(path, { srcRoot, type = undefined }) { 18 | if (type) { 19 | this.type = type; 20 | } else { 21 | Object.keys(lib).forEach(type => { 22 | if (lib[type].check && lib[type].check(path)) { 23 | this.type = type; 24 | return 0; 25 | } 26 | }) 27 | if (!this.type) { 28 | this.type = fs.statSync(path).isDirectory() ? 'folder' : 'file'; 29 | } 30 | } 31 | 32 | lib[this.type].init(this, path, srcRoot); 33 | } 34 | } 35 | 36 | module.exports = File; -------------------------------------------------------------------------------- /script/render/render.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | marked: require('./modules/marked'), 3 | markex: require('./modules/markex'), 4 | } -------------------------------------------------------------------------------- /script/render/type/file.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | init: ($, pathname, source_root) => { 6 | $.path = pathname = path.normalize(pathname); 7 | $.uri = path.normalize('/' + path.relative(source_root, $.path)); 8 | }, 9 | 10 | render: ($) => { 11 | if (!fs.existsSync($.path)) { 12 | return { code: 404 }; 13 | } else { 14 | return { 15 | code: 200, 16 | type: 'file', 17 | res: { 18 | path: $.path 19 | } 20 | }; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /script/render/type/folder.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const lodash = require('lodash'); 3 | 4 | const utils = require('../utils'); 5 | 6 | const perPageLimit = 10; 7 | 8 | module.exports = { 9 | init: ($, pathname, source_root) => { 10 | $.path = pathname = path.normalize(pathname); 11 | $.uri = path.normalize('/' + path.relative(source_root, $.path) + '/'); 12 | }, 13 | 14 | render: ($, options) => { 15 | let articles = utils.listFiles($.path); 16 | articles = lodash.filter(articles, o => (o.isPost)); 17 | articles = articles.map(o => ({ file: o, config: o.render({ submodule: ['config'] }).res.arguments.article })); 18 | articles = lodash.filter(articles, o => (!o.config.hide)); 19 | articles = lodash.sortBy(articles, o => (o.config.date ? -parseInt(o.config.date.format('x')) : Infinity)); 20 | articles = articles.map(o => o.file); 21 | 22 | let multiPageArguments = {}; 23 | if (options.allowMultiPage) { 24 | const page = options.req.page || 1; 25 | multiPageArguments = { 26 | page, 27 | max_page: Math.ceil(articles.length / perPageLimit), 28 | } 29 | articles = articles.slice(perPageLimit * (page - 1), perPageLimit * page); 30 | } 31 | 32 | return { 33 | code: 200, 34 | type: 'page', 35 | res: { 36 | template: 'archive', 37 | arguments: { 38 | title: $.path == router.root ? '/' : path.basename($.path) + ' - 文件夹', 39 | articles: articles, 40 | ...multiPageArguments 41 | } 42 | } 43 | }; 44 | } 45 | } -------------------------------------------------------------------------------- /script/render/types.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | file: require('./type/file'), 3 | folder: require('./type/folder'), 4 | markdown: require('./type/markdown'), 5 | todolist: require('./type/todolist'), 6 | } -------------------------------------------------------------------------------- /script/render/utils.js: -------------------------------------------------------------------------------- 1 | const cheerio = require('cheerio'); 2 | 3 | let $ = cheerio.load(''); 4 | 5 | const utils = { 6 | isNumberChar: function(c) { 7 | return '0'.charCodeAt() <= c.charCodeAt() && c.charCodeAt() <= '9'.charCodeAt(); 8 | }, 9 | 10 | createBreadcrumb: function (uri) { 11 | let breadcrumb = []; 12 | let href = '/'; 13 | Array.from(uri.split('/')).forEach(pathname => { 14 | if (!pathname) { return; } 15 | href = href + pathname + '/' 16 | breadcrumb.push({ 17 | name: pathname, 18 | href: href, 19 | }) 20 | }); 21 | return breadcrumb; 22 | }, 23 | 24 | listFiles: (pathname) => { 25 | let res = [] 26 | Object.values(router.routes).forEach(file => { 27 | if (file.path.startsWith(pathname)) { 28 | res.push(file); 29 | } 30 | }); 31 | return res; 32 | }, 33 | 34 | createElement: (tag, html = '', actions = {}) => { 35 | let element = $('<' + tag + '/>'); 36 | if (html) element.html(html); 37 | Object.keys(actions).forEach(key => { 38 | element[key](actions[key]); 39 | }) 40 | return $.html(element); 41 | }, 42 | 43 | decodeHTML: (content) => { 44 | return $($('
').html(content)).text(); 45 | }, 46 | 47 | getProblemLink: (text) => { 48 | const table = { 49 | '洛谷': { 50 | regex: [/^洛谷(\d+)$/, /^洛谷P(\d+)$/i, /^lg(\d+)$/i, /^luogu(\d+)$/i], 51 | link: (match) => `https://www.luogu.com.cn/problem/P${match[1]}`, 52 | }, 53 | 'LOJ': { 54 | regex: [/^loj(\d+)$/i, /^LibreOJ(\d+)$/i,], 55 | link: (match) => `https://loj.ac/problem/${match[1]}` 56 | }, 57 | 'UOJ': { 58 | regex: [/^uoj(\d+)$/i,], 59 | link: (match) => `http://uoj.ac/problem/${match[1]}` 60 | }, 61 | 'CF': { 62 | regex: [/^cf(\d+)([a-z]\d*)$/i], 63 | link: (match) => `https://codeforces.com/contest/${match[1]}/problem/${match[2]}` 64 | }, 65 | 'GYM': { 66 | regex: [/^gym(\d+)([a-z]\d*)$/i], 67 | link: (match) => `https://codeforces.com/gym/${match[1]}/problem/${match[2]}` 68 | }, 69 | 'HDU': { 70 | regex: [/^hdu(\d+)$/i], 71 | link: (match) => `http://acm.hdu.edu.cn/showproblem.php?pid=${match[1]}` 72 | }, 73 | 'ZOJ': { 74 | regex: [/^zoj(\d+)$/i], 75 | // link: (match) => `http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=${match[1]}` 76 | link: (match) => `https://vjudge.net/problem/ZOJ-${match[1]}/origin` 77 | }, 78 | 'Virtual Judge': { 79 | regex: [/^vj-([^-]+)-([^-]+)/i], 80 | link: (match) => `https://vjudge.net/problem/${match[1]}-${match[2]}` 81 | } 82 | } 83 | text = String(text); 84 | let result = null; 85 | try { 86 | Object.keys(table).forEach(name => { 87 | if (result) return; 88 | table[name].regex.forEach(regex => { 89 | if (result) return; 90 | let matched = text.match(regex); 91 | if (matched) { 92 | result = { 93 | link: table[name].link(matched, text), 94 | name: name 95 | }; 96 | } 97 | }); 98 | }); 99 | } catch (e) { 100 | console.error(text); 101 | console.error(e); 102 | return null; 103 | } 104 | return result; 105 | }, 106 | }; 107 | 108 | module.exports = utils; -------------------------------------------------------------------------------- /script/router.js: -------------------------------------------------------------------------------- 1 | const url = require('url'); 2 | const path = require('path'); 3 | 4 | const config = require('./global').config; 5 | const { listFiles } = require('./render/index'); 6 | 7 | const retiredTimeLimit = 1000 * 30; // 30 seconds 8 | 9 | let router = { 10 | root: process.env['YUYU_SOURCE'] || path.join(__dirname, '../src'), 11 | routes: {}, 12 | lastScanTime: -1, 13 | 14 | scan: function () { 15 | if (Date.now() - this.lastScanTime <= retiredTimeLimit) { 16 | return; 17 | } 18 | 19 | let fileList = listFiles(router.root); 20 | router.routes = {}; 21 | fileList.forEach(file => { 22 | let satisify = true; 23 | file.path.split('/').forEach(part => { 24 | satisify &= !config.ignore.includes(part); 25 | }); 26 | if (satisify) { 27 | if (file.uri) file.uri = file.uri.replace(/\\/g, '/'); 28 | if (file.dirUri) file.dirUri = file.dirUri.replace(/\\/g, '/'); 29 | router.routes[file.uri] = file; 30 | } 31 | }); 32 | 33 | this.lastScanTime = Date.now(); 34 | }, 35 | 36 | data: function (req, options) { 37 | let pathname = decodeURI(url.parse(req.url).pathname); 38 | 39 | if (!Object.keys(router.routes).includes(pathname)) { 40 | if (Object.keys(router.routes).includes(pathname + '/')) { 41 | return { code: 302, res: { url: pathname + '/' }, }; 42 | } else { 43 | return { code: 404 }; 44 | } 45 | } 46 | return router.routes[pathname].render({ 47 | req: req, 48 | options: options 49 | }); 50 | }, 51 | 52 | }; 53 | 54 | router.scan(); 55 | 56 | module.exports = router; 57 | -------------------------------------------------------------------------------- /script/routes/editor.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | 7 | const config = require('../global').config; 8 | 9 | if (config.option.allow_edit) { 10 | router.get('/', function (req, res) { 11 | let uri = req.query.p; 12 | let success = false; 13 | let data = {}; 14 | Object.values(global.router.routes).forEach(file => { 15 | if (!success && file.type == 'markdown' && file.uri == uri) { 16 | let text = fs.readFileSync(file.path).toString(); 17 | 18 | success = true; 19 | data = { 20 | type: 'post', 21 | text: text, 22 | uri: uri 23 | } 24 | } 25 | }); 26 | res.render('editor', { 27 | title: '编辑器', 28 | success: success, 29 | data: data, 30 | }); 31 | }); 32 | } 33 | 34 | if (config.option.allow_edit) { 35 | router.post('/', function (req, res) { 36 | let text = req.body.text; 37 | let type = req.body.type; 38 | let uri = req.body.uri; 39 | 40 | let success = false; 41 | 42 | if (type == 'post') { 43 | Object.values(global.router.routes).forEach(file => { 44 | if (!success && file.type == 'markdown' && file.uri == uri) { 45 | success = true; 46 | fs.writeFileSync(file.path, text); 47 | } 48 | }); 49 | } 50 | 51 | res.json({ 52 | code: 200, 53 | success: success, 54 | }); 55 | }); 56 | } 57 | 58 | module.exports = router; -------------------------------------------------------------------------------- /script/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | const path = require('path'); 5 | 6 | const global_arguments = require('../global'); 7 | 8 | router.get(/^.*$/, function (req, res, next) { 9 | global.router.scan(); 10 | 11 | let data = global.router.data(req, { allowMultiPage: true }); 12 | if (data.code == 200) { 13 | if (data.type == 'file') { 14 | res.sendFile(data.res.path); 15 | } else if (data.type == 'page') { 16 | res.render(data.res.template, { page: req.page, ...global_arguments, ...data.res.arguments }); 17 | } 18 | } else if (data.code == 301) { 19 | res.redirect(301, data.res.url); 20 | } else if (data.code == 302) { 21 | res.redirect(302, data.res.url); 22 | } else if (data.code == 404) { 23 | next(); 24 | } else { 25 | res.locals.message = 'Render Error: ' + JSON.stringify(data); 26 | res.locals.error = {}; 27 | res.status(data.code); 28 | res.render('error'); 29 | } 30 | }); 31 | 32 | 33 | router.get('/tag/:tagName', function (req, res) { 34 | global.router.scan(); 35 | 36 | let tagName = req.params.tagName; 37 | let articles = []; 38 | 39 | Object.values(global.router.routes).forEach(file => { 40 | if (!file.isPost) { return; } 41 | let config = file.render({ submodule: ['config'] }).res.arguments.article; 42 | if (config.tag && config.tag.includes(tagName)) { 43 | articles.push(file); 44 | } 45 | }); 46 | 47 | res.render('archive', { 48 | title: tagName + ' - 标签', 49 | articles: articles, 50 | }); 51 | }); 52 | 53 | 54 | router.get('/search/:keyword', function (req, res, next) { 55 | global.router.scan(); 56 | 57 | let keyword = decodeURIComponent(req.params.keyword); 58 | let keywordRegExp = new RegExp(keyword, 'i'); 59 | let articles = []; 60 | let unsortedArticles = []; 61 | 62 | Object.values(global.router.routes).forEach(file => { 63 | if (!file.isPost) { return; } 64 | let config = file.render({ submodule: ['config'] }).res.arguments.article; 65 | let key = 0; 66 | if (file.uri && file.uri.match(keywordRegExp)) { 67 | key += 1000; 68 | } 69 | if (config.title && config.title.match(keywordRegExp)) { 70 | key += 900; 71 | } 72 | // console.log(config.title); 73 | if (key) { 74 | unsortedArticles.push({ file: file, key: key }); 75 | } 76 | }); 77 | 78 | // console.log(keyword); 79 | 80 | articles = unsortedArticles 81 | .sort((a, b) => { 82 | if (a.key != b.key) return a.key - b.key; 83 | }) 84 | .map((pair) => (pair.file)); 85 | console.log(articles.length); 86 | 87 | res.render('archive', { 88 | title: keyword + ' - 搜索结果', 89 | articles: articles, 90 | }); 91 | }); 92 | 93 | 94 | router.get('/timeline', function (req, res, next) { 95 | let articles = []; 96 | 97 | Object.values(global.router.routes).forEach(file => { 98 | if (!file.isPost) { return; } 99 | let config = file.render({ submodule: ['config'] }).res.arguments.article; 100 | if (config.hide || !config.date) { return; } 101 | articles.push(config); 102 | }); 103 | articles = articles.sort(function (a, b) { 104 | return b.date.format('x') - a.date.format('x'); 105 | }); 106 | 107 | res.render('timeline', { 108 | title: '时间轴', 109 | articles: articles, 110 | }) 111 | }); 112 | 113 | 114 | module.exports = router; -------------------------------------------------------------------------------- /script/routes/middleware/page.js: -------------------------------------------------------------------------------- 1 | module.exports = function (req, res, next) { 2 | if (req.query && req.query.page && !isNaN(parseInt(req.query.page)) && parseInt(req.query.page) >= 1) { 3 | req.page = parseInt(req.query.page); 4 | console.log('[page]', req.page); 5 | } 6 | 7 | next(); 8 | }; -------------------------------------------------------------------------------- /script/spider.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./spider/index'); -------------------------------------------------------------------------------- /script/spider/index.js: -------------------------------------------------------------------------------- 1 | const methods = [ 2 | require('./methods/yhx12243'), 3 | ]; 4 | 5 | module.exports = async function (url) { 6 | if (url.startsWith('http://')) url = url.slice(7); 7 | if (url.startsWith('https://')) url = url.slice(8); 8 | 9 | for (let id = 0; id < methods.length; id++) { 10 | let satisfy = false; 11 | methods[id].prefix.forEach(prefix => { 12 | if (url.startsWith(prefix)) satisfy = true; 13 | }); 14 | 15 | if (satisfy) { 16 | return await methods[id].spider(url); 17 | } 18 | } 19 | return null; 20 | }; -------------------------------------------------------------------------------- /script/spider/methods/yhx12243.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const cheerio = require('cheerio'); 4 | const superagent = require('superagent'); 5 | 6 | const turndown = require('../turndown'); 7 | 8 | const yhx12243Spider = { 9 | prefix: ['yhx-12243.github.io/OI-transit'], 10 | 11 | spider: async function (url, dir) { 12 | let name = url.match(/yhx\-12243\.github\.io\/OI\-transit\/records\/(.+)\.html/); 13 | name = name && name[1] ? name[1].replace('%3b', ',').toLowerCase() : 'noname'; 14 | 15 | if (!url.startsWith('http://') && !url.startsWith('https://')) { 16 | url = 'https://' + url; 17 | } 18 | 19 | let res = await superagent.get(url); 20 | let $ = cheerio.load(res.text); 21 | 22 | let data = { 23 | title: $('html>head>title').text() 24 | .replace(/\[/g, '「') 25 | .replace(/\]/g, '」') 26 | .replace('CodeforcesGym', 'GYM') 27 | .replace('Codeforces', 'CF') 28 | .replace('uoj', 'UOJ') 29 | .replace('loj', 'LOJ') 30 | .replace('soj', 'StupidOJ') 31 | .replace('lydsy', 'BZOJ') 32 | .replace('lg', '洛谷'), 33 | }; 34 | 35 | $('img').each(function () { 36 | let alt = $(this).attr('alt'); 37 | $(this).attr('alt', 'center|zoom:80%' + (alt ? '|' + alt : '')); 38 | 39 | let src = $(this).attr('src'); 40 | if (!src.startsWith('http://') && !src.startsWith('https://')) { 41 | $(this).attr('src', 'https://yhx-12243.github.io/OI-transit/records/' + src); 42 | } 43 | }); 44 | 45 | $('body>h1, body>h2, body>h3, body>h4').each(function () { 46 | if ($(this).text() == '题目大意') $(this).html(''); 47 | if ($(this).text() == '题目描述') $(this).html(''); 48 | if ($(this).text() == '题解') $(this).text('yhx-12243 的题解'); 49 | }); 50 | 51 | // if (data.title == '访问受限提醒') { // SB gfw??? 52 | // console.log(res.text); 53 | // } 54 | 55 | return { 56 | name: name, 57 | data: data, 58 | text: turndown($('body').html()).replace('### yhx-12243 的题解', '\n\n\n### yhx-12243 的题解'), 59 | }; 60 | }, 61 | }; 62 | 63 | module.exports = yhx12243Spider; 64 | 65 | if (require.main == module) { 66 | const url = 'http://localhost:3000/noname.txt'; 67 | 68 | yhx12243Spider.spider(url).then(console.log); 69 | } -------------------------------------------------------------------------------- /script/spider/turndown.js: -------------------------------------------------------------------------------- 1 | const TurndownService = require('turndown'); 2 | turndownService = new TurndownService({ 3 | codeBlockStyle: 'fenced', 4 | fence: '```', 5 | }); 6 | 7 | function turndown(html) { 8 | text = turndownService.turndown(html); 9 | text = text 10 | .replace(/(?<=\$.*)\\\_(?=.*\$)/g, '\_') 11 | .replace(/(?<=\$.*)\\\[(?=.*\$)/g, '\[') 12 | .replace(/(?<=\$.*)\\\](?=.*\$)/g, '\]') 13 | .replace(/(?<=\$.*)\\\\(?=.*\$)/g, '\\') 14 | return text; 15 | } 16 | 17 | module.exports = turndown; -------------------------------------------------------------------------------- /script/www.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | module.exports = function(targetPort = null) { 4 | var app = require('../script/app'); 5 | var debug = require('debug')('app:server'); 6 | var http = require('http'); 7 | 8 | var port = normalizePort(process.env.PORT || targetPort || '3000'); 9 | app.set('port', port); 10 | 11 | var server = http.createServer(app); 12 | server.listen(port); 13 | server.on('error', onError); 14 | server.on('listening', onListening); 15 | 16 | function normalizePort(val) { 17 | var port = parseInt(val, 10); 18 | if (isNaN(port)) { 19 | return val; 20 | } 21 | if (port >= 0) { 22 | return port; 23 | } 24 | return false; 25 | } 26 | 27 | function onError(error) { 28 | if (error.syscall !== 'listen') { 29 | throw error; 30 | } 31 | 32 | var bind = typeof port === 'string' 33 | ? 'Pipe ' + port 34 | : 'Port ' + port; 35 | 36 | switch (error.code) { 37 | case 'EACCES': 38 | console.error(bind + ' requires elevated privileges'); 39 | process.exit(1); 40 | break; 41 | case 'EADDRINUSE': 42 | console.error(bind + ' is already in use'); 43 | process.exit(1); 44 | break; 45 | default: 46 | throw error; 47 | } 48 | } 49 | 50 | function onListening() { 51 | var addr = server.address(); 52 | var bind = typeof addr === 'string' 53 | ? 'pipe ' + addr 54 | : 'port ' + addr.port; 55 | debug('Listening on ' + bind); 56 | } 57 | } 58 | 59 | if (require.main == module) { 60 | module.exports(); 61 | } -------------------------------------------------------------------------------- /static/css/archive.less: -------------------------------------------------------------------------------- 1 | #archive { 2 | width: 95%; 3 | margin: auto; 4 | .archive-article { 5 | &>.ui.card { 6 | width: 97.5%; 7 | margin: auto; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /static/css/article.less: -------------------------------------------------------------------------------- 1 | #article { 2 | width: 95%; 3 | margin: auto; 4 | 5 | &>.ui.card { 6 | width: 97.5%; 7 | margin: auto; 8 | } 9 | 10 | .article-tag { 11 | margin-right: 8px; 12 | color: #a0a0a0; 13 | transition: 0.2s color; 14 | font-size: .92em; 15 | 16 | &:hover { 17 | color: #4183c4; 18 | } 19 | } 20 | 21 | .article-title { 22 | padding-top: .42em; 23 | padding-bottom: .42em; 24 | font-size: 1.9em; 25 | line-height: 1.22em; 26 | } 27 | 28 | .ui.divider { 29 | margin: 37.5px -2333px 37.5px; 30 | } 31 | 32 | .view { 33 | display: flex; 34 | flex-direction: row; 35 | 36 | .left { 37 | width: calc(100% - 280px); 38 | 39 | .content { 40 | width: 100%; 41 | } 42 | } 43 | 44 | .right { 45 | width: 280px; 46 | padding-left: 40px; 47 | 48 | .ui.menu { 49 | position: sticky; 50 | align-self: start; 51 | top: 80px; 52 | border-right: none; 53 | border-left-width: 2px; 54 | border-left-style: solid; 55 | border-left-color: rgba(34,36,38,.15); 56 | 57 | .item { 58 | border-right: none; 59 | border-left-style: solid; 60 | border-left-color: transparent; 61 | border-left-width: 2px; 62 | margin: 0 0 0 -2px; 63 | 64 | &>i.icon{ 65 | float: left; 66 | margin: 0 .5em 0 0; 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /static/css/editor.less: -------------------------------------------------------------------------------- 1 | #editor-submit { 2 | } -------------------------------------------------------------------------------- /static/css/markdown.less: -------------------------------------------------------------------------------- 1 | .md { 2 | @fontSize: 14px; 3 | 4 | h1, 5 | h2, 6 | h3, 7 | h4, 8 | h5, 9 | h6 { 10 | font-weight: normal; 11 | margin-top: 1.2em; 12 | margin-bottom: 0.6em; 13 | } 14 | 15 | h1 { 16 | font-size: 2em; 17 | } 18 | 19 | h2 { 20 | font-size: 1.6em; 21 | } 22 | 23 | h3 { 24 | font-size: 1.5em; 25 | } 26 | 27 | h4 { 28 | font-size: 1.3em; 29 | } 30 | 31 | h5 { 32 | font-size: 1.2em; 33 | } 34 | 35 | h6 { 36 | font-size: 1.2em; 37 | } 38 | 39 | p { 40 | font-size: @fontSize; 41 | line-height: 1.5em; 42 | margin-bottom: 0.8em !important; 43 | 44 | &:last-child { 45 | margin-bottom: 0 !important; 46 | } 47 | } 48 | 49 | hr { 50 | margin: 30px; 51 | border: none; 52 | height: 1px; 53 | width: calc(100% - 60px); 54 | background: #c0c0c0; 55 | } 56 | 57 | li { 58 | font-size: @fontSize; 59 | line-height: 1.75em; 60 | } 61 | 62 | pre { 63 | tab-size: 2; 64 | box-shadow: 0 1px 2px 0 rgba(34, 36, 38, .15); 65 | margin: 1rem 0; 66 | padding: 1em 1em; 67 | border-radius: .28571429rem; 68 | border: 1px solid rgba(34, 36, 38, .15); 69 | } 70 | 71 | .hljs { 72 | font-size: @fontSize * 0.9; 73 | line-height: 1.5em; 74 | padding: 0; 75 | font-family: consolas, Menlo, 'Ubuntu Mono', monospace; 76 | } 77 | 78 | 79 | // plugins 80 | 81 | .md-iframe { 82 | display: block; 83 | margin: auto; 84 | margin-top: 1em; 85 | margin-bottom: 1em; 86 | max-width: 98%; 87 | max-height: 100%; 88 | } 89 | 90 | .md-pdf-viewer { 91 | .md-iframe(); 92 | } 93 | 94 | .md-iframe-onedrive { 95 | .md-iframe(); 96 | } 97 | } -------------------------------------------------------------------------------- /static/css/pagination.less: -------------------------------------------------------------------------------- 1 | #pagination-front, 2 | #pagination-back { 3 | width: 100%; 4 | margin: 10px 0; 5 | text-align: center; 6 | 7 | .ui.pagination { 8 | margin-left: auto !important; 9 | margin-right: auto !important; 10 | } 11 | } -------------------------------------------------------------------------------- /static/css/style.less: -------------------------------------------------------------------------------- 1 | @import "article.less"; 2 | @import "archive.less"; 3 | @import "todolist.less"; 4 | @import "editor.less"; 5 | 6 | @import "pagination.less"; 7 | 8 | @import "markdown.less"; -------------------------------------------------------------------------------- /static/css/todolist.less: -------------------------------------------------------------------------------- 1 | #todolist { 2 | width: 95%; 3 | margin: auto; 4 | 5 | &>.ui.styled.accordion { 6 | width: 97.5%; 7 | margin: auto; 8 | 9 | .accordion { 10 | width: 100%; 11 | } 12 | } 13 | 14 | .__todolist-item-color(@p) { 15 | &.item-color-red { 16 | color: rgba(255, 0, 0, @p); 17 | } 18 | 19 | &.item-color-green { 20 | color: rgba(55, 225, 0, @p); 21 | } 22 | 23 | &.item-color-yellow { 24 | color: rgba(215, 195, 0, @p); 25 | } 26 | 27 | &.item-color-black { 28 | color: rgba(0, 0, 0, @p); 29 | } 30 | } 31 | 32 | .ui.accordion { 33 | .title { 34 | .__todolist-item-color(.6); 35 | } 36 | 37 | .title:hover, 38 | .active.title { 39 | .__todolist-item-color(.95); 40 | } 41 | } 42 | 43 | .article-title { 44 | padding-top: .6em; 45 | padding-bottom: 1.2em; 46 | text-align: center; 47 | font-size: 2.2em; 48 | line-height: 1.2em; 49 | } 50 | } -------------------------------------------------------------------------------- /static/js/editor.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | let text = decodeURIComponent(__yuyu_editor_text) 3 | .replace(/'/g, '\''); 4 | let data = JSON.parse(decodeURIComponent(__yuyu_editor_data)); 5 | let { type, uri } = data; 6 | 7 | $('#editor-submit').click(function () { 8 | text = monaco_editor.getValue(); 9 | 10 | // console.log('data: ', data); 11 | // console.log('text: ', text); 12 | $.post('/edit', { 13 | text: text, 14 | type: type, 15 | uri: uri, 16 | }, function () { 17 | window.location.href = uri; 18 | }); 19 | }) 20 | })(); -------------------------------------------------------------------------------- /static/js/modules/readmode.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | let windowHeight, clientHeight, contentHeight; 3 | let pageNow, pageCounter; 4 | 5 | function moveToPage () { 6 | if (pageNow < 1) pageNow = 1; 7 | if (pageNow > pageCounter) pageNow = pageCounter; 8 | console.log('[readmode] page', pageNow, '/', pageCounter); 9 | $('#reader-container').css('margin-top', `-${(pageNow - 1) * perpageHeight}px`); 10 | } 11 | 12 | function render () { 13 | windowHeight = document.body.clientHeight; 14 | clientHeight = document.body.clientHeight - 60; 15 | 16 | $('body').css('height', '0'); 17 | $('#container').prop('outerHTML', ` 18 |
19 |
20 |
21 | ${$('#container').html()} 22 |
23 |
24 |
25 | 26 | 27 | 28 | `); 29 | 30 | contentHeight = $('#reader-container').prop('clientHeight'); 31 | perpageHeight = clientHeight - 40; 32 | pageCounter = 1 + Math.ceil((contentHeight - clientHeight) / perpageHeight); 33 | pageNow = 1; 34 | 35 | moveToPage(pageNow); 36 | } 37 | 38 | function enable() { 39 | $(document).ready(function () { 40 | render(); 41 | }); 42 | window.readmode = { 43 | nextPage: function () { ++pageNow, moveToPage(); }, 44 | prevPage: function () { --pageNow, moveToPage(); }, 45 | }; 46 | } 47 | 48 | // Cookies.set('yuyu.options.readmode', 'on'); 49 | let enabled = Cookies.get('yuyu.options.readmode') ? true : false; 50 | if (enabled) { 51 | enable(); 52 | } 53 | })(); -------------------------------------------------------------------------------- /static/js/pagination.js: -------------------------------------------------------------------------------- 1 | function replaceGetArguments(src, arg, val) { 2 | if (src.match(arg + '=([^&]*)')) { 3 | return src.replace(RegExp('(' + arg + '=)([^&]*)', 'gi'), arg + '=' + val); 4 | } else if (src) { 5 | return src + '&' + arg + '=' + val; 6 | } else { 7 | return arg + '=' + val; 8 | } 9 | } 10 | 11 | $('#pagination-front a, #pagination-back a').click(function () { 12 | const page = $(this).text().trim(); 13 | console.log('change to', page, '...'); 14 | 15 | window.location.search = replaceGetArguments(window.location.search, 'page', page); 16 | }); -------------------------------------------------------------------------------- /static/js/ui.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | $('.ui.menu .ui.dropdown').dropdown({ 3 | on: 'hover' 4 | }); 5 | $('.ui.menu a.item').on('click', function () { 6 | $(this) 7 | .addClass('active') 8 | .siblings().removeClass('active'); 9 | }); 10 | }); 11 | 12 | 13 | // search 14 | (function () { 15 | if (location.pathname.startsWith('/search/')) { 16 | let keyword = decodeURIComponent(location.pathname.replace(/^\/search\//, '')); 17 | // console.log(keyword); 18 | $('#search-input').val(keyword); 19 | } 20 | 21 | function search() { 22 | if ($('#search-input').val()) { 23 | let keyword = encodeURIComponent($('#search-input').val()); 24 | window.location.href = '/search/' + keyword; 25 | } 26 | } 27 | 28 | $('#search-button').bind('click', function () { 29 | search(); 30 | }); 31 | 32 | $('#search-input').bind('keypress', function (e) { 33 | e = e || window.event; 34 | if (e.keyCode == 13) { search(); } 35 | }); 36 | })(); -------------------------------------------------------------------------------- /static/lib/highlight/default.css: -------------------------------------------------------------------------------- 1 | .hljs{display:block;overflow-x:auto;padding:.5em;background:#f0f0f0}.hljs,.hljs-subst{color:#444}.hljs-comment{color:#888}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#bc6060}.hljs-literal{color:#78a960}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta-string{color:#4d99bf}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} -------------------------------------------------------------------------------- /static/lib/highlight/tomorrow.css: -------------------------------------------------------------------------------- 1 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 2 | 3 | /* Tomorrow Comment */ 4 | .hljs-comment, 5 | .hljs-quote { 6 | color: #8e908c; 7 | } 8 | 9 | /* Tomorrow Red */ 10 | .hljs-variable, 11 | .hljs-template-variable, 12 | .hljs-tag, 13 | .hljs-name, 14 | .hljs-selector-id, 15 | .hljs-selector-class, 16 | .hljs-regexp, 17 | .hljs-deletion { 18 | color: #c82829; 19 | } 20 | 21 | /* Tomorrow Orange */ 22 | .hljs-number, 23 | .hljs-built_in, 24 | .hljs-builtin-name, 25 | .hljs-literal, 26 | .hljs-type, 27 | .hljs-params, 28 | .hljs-meta, 29 | .hljs-link { 30 | color: #f5871f; 31 | } 32 | 33 | /* Tomorrow Yellow */ 34 | .hljs-attribute { 35 | color: #eab700; 36 | } 37 | 38 | /* Tomorrow Green */ 39 | .hljs-string, 40 | .hljs-symbol, 41 | .hljs-bullet, 42 | .hljs-addition { 43 | color: #718c00; 44 | } 45 | 46 | /* Tomorrow Blue */ 47 | .hljs-title, 48 | .hljs-section { 49 | color: #4271ae; 50 | } 51 | 52 | /* Tomorrow Purple */ 53 | .hljs-keyword, 54 | .hljs-selector-tag { 55 | color: #8959a8; 56 | } 57 | 58 | .hljs { 59 | display: block; 60 | overflow-x: auto; 61 | background: white; 62 | color: #4d4d4c; 63 | padding: 0.5em; 64 | } 65 | 66 | .hljs-emphasis { 67 | font-style: italic; 68 | } 69 | 70 | .hljs-strong { 71 | font-weight: bold; 72 | } -------------------------------------------------------------------------------- /static/lib/js.cookie.min.js: -------------------------------------------------------------------------------- 1 | /*! js-cookie v2.2.1 | MIT */ 2 | 3 | !function(a){var b;if("function"==typeof define&&define.amd&&(define(a),b=!0),"object"==typeof exports&&(module.exports=a(),b=!0),!b){var c=window.Cookies,d=window.Cookies=a();d.noConflict=function(){return window.Cookies=c,d}}}(function(){function a(){for(var a=0,b={};a>","&^","+=","-=","*=","/=","%=","&=","|=","^=","<<=",">>=","&^=","&&","||","<-","++","--","==","<",">","=","!","!=","<=",">=",":=","...","(",")","","]","{","}",",",";",".",":"],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\d+[eE]([\-+]?\d+)?/,"number.float"],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F]/,"number.hex"],[/0[0-7']*[0-7]/,"number.octal"],[/0[bB][0-1']*[0-1]/,"number.binary"],[/\d[\d']*/,"number"],[/\d/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"],[/`/,"string","@rawstring"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@doccomment"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],doccomment:[[/[^\/*]+/,"comment.doc"],[/\/\*/,"comment.doc.invalid"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],rawstring:[[/[^\`]/,"string"],[/`/,"string","@pop"]]}}})); -------------------------------------------------------------------------------- /static/lib/monaco-editor/vs/basic-languages/graphql/graphql.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * monaco-languages version: 2.1.1(425b0e3c9ea2067410b8f90e0f30de383188c418) 4 | * Released under the MIT license 5 | * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md 6 | *-----------------------------------------------------------------------------*/ 7 | define("vs/basic-languages/graphql/graphql",["require","exports"],(function(e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.language=n.conf=void 0,n.conf={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"""',close:'"""',notIn:["string","comment"]},{open:'"',close:'"',notIn:["string","comment"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"""',close:'"""'},{open:'"',close:'"'}],folding:{offSide:!0}},n.language={defaultToken:"invalid",tokenPostfix:".gql",keywords:["null","true","false","query","mutation","subscription","extend","schema","directive","scalar","type","interface","union","enum","input","implements","fragment","on"],typeKeywords:["Int","Float","String","Boolean","ID"],directiveLocations:["SCHEMA","SCALAR","OBJECT","FIELD_DEFINITION","ARGUMENT_DEFINITION","INTERFACE","UNION","ENUM","ENUM_VALUE","INPUT_OBJECT","INPUT_FIELD_DEFINITION","QUERY","MUTATION","SUBSCRIPTION","FIELD","FRAGMENT_DEFINITION","FRAGMENT_SPREAD","INLINE_FRAGMENT","VARIABLE_DEFINITION"],operators:["=","!","?",":","&","|"],symbols:/[=!?:&|]+/,escapes:/\\(?:["\\\/bfnrt]|u[0-9A-Fa-f]{4})/,tokenizer:{root:[[/[a-z_][\w$]*/,{cases:{"@keywords":"keyword","@default":"key.identifier"}}],[/[$][\w$]*/,{cases:{"@keywords":"keyword","@default":"argument.identifier"}}],[/[A-Z][\w\$]*/,{cases:{"@typeKeywords":"keyword","@default":"type.identifier"}}],{include:"@whitespace"},[/[{}()\[\]]/,"@brackets"],[/@symbols/,{cases:{"@operators":"operator","@default":""}}],[/@\s*[a-zA-Z_\$][\w\$]*/,{token:"annotation",log:"annotation token: $0"}],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F]+/,"number.hex"],[/\d+/,"number"],[/[;,.]/,"delimiter"],[/"""/,{token:"string",next:"@mlstring",nextEmbedded:"markdown"}],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,{token:"string.quote",bracket:"@open",next:"@string"}]],mlstring:[[/[^"]+/,"string"],['"""',{token:"string",next:"@pop",nextEmbedded:"@pop"}]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,{token:"string.quote",bracket:"@close",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[/#.*$/,"comment"]]}}})); -------------------------------------------------------------------------------- /static/lib/monaco-editor/vs/basic-languages/ini/ini.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * monaco-languages version: 2.1.1(425b0e3c9ea2067410b8f90e0f30de383188c418) 4 | * Released under the MIT license 5 | * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md 6 | *-----------------------------------------------------------------------------*/ 7 | define("vs/basic-languages/ini/ini",["require","exports"],(function(e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.language=n.conf=void 0,n.conf={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},n.language={defaultToken:"",tokenPostfix:".ini",escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/^\[[^\]]*\]/,"metatag"],[/(^\w+)(\s*)(\=)/,["key","","delimiter"]],{include:"@whitespace"},[/\d+/,"number"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string",'@string."'],[/'/,"string","@string.'"]],whitespace:[[/[ \t\r\n]+/,""],[/^\s*[#;].*$/,"comment"]],string:[[/[^\\"']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/["']/,{cases:{"$#==$S2":{token:"string",next:"@pop"},"@default":"string"}}]]}}})); -------------------------------------------------------------------------------- /static/lib/monaco-editor/vs/basic-languages/java/java.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * monaco-languages version: 2.1.1(425b0e3c9ea2067410b8f90e0f30de383188c418) 4 | * Released under the MIT license 5 | * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md 6 | *-----------------------------------------------------------------------------*/ 7 | define("vs/basic-languages/java/java",["require","exports"],(function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.language=t.conf=void 0,t.conf={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"<",close:">"}],folding:{markers:{start:new RegExp("^\\s*//\\s*(?:(?:#?region\\b)|(?:))")}}},t.language={defaultToken:"",tokenPostfix:".java",keywords:["abstract","continue","for","new","switch","assert","default","goto","package","synchronized","boolean","do","if","private","this","break","double","implements","protected","throw","byte","else","import","public","throws","case","enum","instanceof","return","transient","catch","extends","int","short","try","char","final","interface","static","void","class","finally","long","strictfp","volatile","const","float","native","super","while","true","false"],operators:["=",">","<","!","~","?",":","==","<=",">=","!=","&&","||","++","--","+","-","*","/","&","|","^","%","<<",">>",">>>","+=","-=","*=","/=","&=","|=","^=","%=","<<=",">>=",">>>="],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/@\s*[a-zA-Z_\$][\w\$]*/,"annotation"],[/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/,"number.float"],[/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/,"number.float"],[/0[xX](@hexdigits)[Ll]?/,"number.hex"],[/0(@octaldigits)[Ll]?/,"number.octal"],[/0[bB](@binarydigits)[Ll]?/,"number.binary"],[/(@digits)[fFdD]/,"number.float"],[/(@digits)[lL]?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@javadoc"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],javadoc:[[/[^\/*]+/,"comment.doc"],[/\/\*/,"comment.doc.invalid"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]]}}})); -------------------------------------------------------------------------------- /static/lib/monaco-editor/vs/basic-languages/lua/lua.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * monaco-languages version: 2.1.1(425b0e3c9ea2067410b8f90e0f30de383188c418) 4 | * Released under the MIT license 5 | * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md 6 | *-----------------------------------------------------------------------------*/ 7 | define("vs/basic-languages/lua/lua",["require","exports"],(function(e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.language=n.conf=void 0,n.conf={comments:{lineComment:"--",blockComment:["--[[","]]"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},n.language={defaultToken:"",tokenPostfix:".lua",keywords:["and","break","do","else","elseif","end","false","for","function","goto","if","in","local","nil","not","or","repeat","return","then","true","until","while"],brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.array",open:"[",close:"]"},{token:"delimiter.parenthesis",open:"(",close:")"}],operators:["+","-","*","/","%","^","#","==","~=","<=",">=","<",">","=",";",":",",",".","..","..."],symbols:/[=>]/,"@brackets"],[/[a-zA-Z@#]\w*/,{cases:{"@keywords":"keyword","@default":"identifier"}}],[/[<>=\\+\\-\\*\\/\\^\\|\\~,]|and\\b|or\\b|not\\b]/,"operator"]],whitespace:[[/\s+/,"white"]],comments:[["\\/\\*","comment","@comment"],["\\/\\/+.*","comment"]],comment:[["\\*\\/","comment","@pop"],[".","comment"]],numbers:[[/0[xX][0-9a-fA-F]*(_?[0-9a-fA-F])*/,"number.hex"],[/@decimal((\.@decpart)?([eE][\-+]?@decpart)?)[fF]*/,{cases:{"(\\d)*":"number",$0:"number.float"}}]],strings:[[/'$/,"string.escape","@popall"],[/'/,"string.escape","@stringBody"],[/"$/,"string.escape","@popall"],[/"/,"string.escape","@dblStringBody"]],stringBody:[[/[^\\']+$/,"string","@popall"],[/[^\\']+/,"string"],[/\\./,"string"],[/'/,"string.escape","@popall"],[/\\$/,"string"]],dblStringBody:[[/[^\\"]+$/,"string","@popall"],[/[^\\"]+/,"string"],[/\\./,"string"],[/"/,"string.escape","@popall"],[/\\$/,"string"]]}}})); -------------------------------------------------------------------------------- /static/lib/monaco-editor/vs/basic-languages/pascal/pascal.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * monaco-languages version: 2.1.1(425b0e3c9ea2067410b8f90e0f30de383188c418) 4 | * Released under the MIT license 5 | * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md 6 | *-----------------------------------------------------------------------------*/ 7 | define("vs/basic-languages/pascal/pascal",["require","exports"],(function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.language=t.conf=void 0,t.conf={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"//",blockComment:["{","}"]},brackets:[["{","}"],["[","]"],["(",")"],["<",">"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"}],folding:{markers:{start:new RegExp("^\\s*\\{\\$REGION(\\s\\'.*\\')?\\}"),end:new RegExp("^\\s*\\{\\$ENDREGION\\}")}}},t.language={defaultToken:"",tokenPostfix:".pascal",ignoreCase:!0,brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],keywords:["absolute","abstract","all","and_then","array","as","asm","attribute","begin","bindable","case","class","const","contains","default","div","else","end","except","exports","external","far","file","finalization","finally","forward","generic","goto","if","implements","import","in","index","inherited","initialization","interrupt","is","label","library","mod","module","name","near","not","object","of","on","only","operator","or_else","otherwise","override","package","packed","pow","private","program","protected","public","published","interface","implementation","qualified","read","record","resident","requires","resourcestring","restricted","segment","set","shl","shr","specialize","stored","then","threadvar","to","try","type","unit","uses","var","view","virtual","dynamic","overload","reintroduce","with","write","xor","true","false","procedure","function","constructor","destructor","property","break","continue","exit","abort","while","do","for","raise","repeat","until"],typeKeywords:["boolean","double","byte","integer","shortint","char","longint","float","string"],operators:["=",">","<","<=",">=","<>",":",":=","and","or","+","-","*","/","@","&","^","%"],symbols:/[=><:@\^&|+\-*\/\^%]+/,tokenizer:{root:[[/[a-zA-Z_][\w]*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"identifier"}}],{include:"@whitespace"},[/[{}()\[\]]/,"@brackets"],[/[<>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/\$[0-9a-fA-F]{1,16}/,"number.hex"],[/\d+/,"number"],[/[;,.]/,"delimiter"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/'/,"string","@string"],[/'[^\\']'/,"string"],[/'/,"string.invalid"],[/\#\d+/,"string"]],comment:[[/[^\*\}]+/,"comment"],[/\}/,"comment","@pop"],[/[\{]/,"comment"]],string:[[/[^\\']+/,"string"],[/\\./,"string.escape.invalid"],[/'/,{token:"string.quote",bracket:"@close",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,"white"],[/\{/,"comment","@comment"],[/\/\/.*$/,"comment"]]}}})); -------------------------------------------------------------------------------- /static/lib/monaco-editor/vs/basic-languages/r/r.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * monaco-languages version: 2.1.1(425b0e3c9ea2067410b8f90e0f30de383188c418) 4 | * Released under the MIT license 5 | * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md 6 | *-----------------------------------------------------------------------------*/ 7 | define("vs/basic-languages/r/r",["require","exports"],(function(e,o){"use strict";Object.defineProperty(o,"__esModule",{value:!0}),o.language=o.conf=void 0,o.conf={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}]},o.language={defaultToken:"",tokenPostfix:".r",roxygen:["@param","@return","@name","@rdname","@examples","@include","@docType","@S3method","@TODO","@aliases","@alias","@assignee","@author","@callGraphDepth","@callGraph","@callGraphPrimitives","@concept","@exportClass","@exportMethod","@exportPattern","@export","@formals","@format","@importClassesFrom","@importFrom","@importMethodsFrom","@import","@keywords","@method","@nord","@note","@references","@seealso","@setClass","@slot","@source","@title","@usage"],constants:["NULL","FALSE","TRUE","NA","Inf","NaN ","NA_integer_","NA_real_","NA_complex_","NA_character_ ","T","F","LETTERS","letters","month.abb","month.name","pi","R.version.string"],keywords:["break","next","return","if","else","for","in","repeat","while","array","category","character","complex","double","function","integer","list","logical","matrix","numeric","vector","data.frame","factor","library","require","attach","detach","source"],special:["\\n","\\r","\\t","\\b","\\a","\\f","\\v","\\'",'\\"',"\\\\"],brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.bracket"},{open:"(",close:")",token:"delimiter.parenthesis"}],tokenizer:{root:[{include:"@numbers"},{include:"@strings"},[/[{}\[\]()]/,"@brackets"],{include:"@operators"},[/#'/,"comment.doc","@roxygen"],[/(^#.*$)/,"comment"],[/\s+/,"white"],[/[,:;]/,"delimiter"],[/@[a-zA-Z]\w*/,"tag"],[/[a-zA-Z]\w*/,{cases:{"@keywords":"keyword","@constants":"constant","@default":"identifier"}}]],roxygen:[[/@\w+/,{cases:{"@roxygen":"tag","@eos":{token:"comment.doc",next:"@pop"},"@default":"comment.doc"}}],[/\s+/,{cases:{"@eos":{token:"comment.doc",next:"@pop"},"@default":"comment.doc"}}],[/.*/,{token:"comment.doc",next:"@pop"}]],numbers:[[/0[xX][0-9a-fA-F]+/,"number.hex"],[/-?(\d*\.)?\d+([eE][+\-]?\d+)?/,"number"]],operators:[[/<{1,2}-/,"operator"],[/->{1,2}/,"operator"],[/%[^%\s]+%/,"operator"],[/\*\*/,"operator"],[/%%/,"operator"],[/&&/,"operator"],[/\|\|/,"operator"],[/<>/,"operator"],[/[-+=&|!<>^~*/:$]/,"operator"]],strings:[[/'/,"string.escape","@stringBody"],[/"/,"string.escape","@dblStringBody"]],stringBody:[[/\\./,{cases:{"@special":"string","@default":"error-token"}}],[/'/,"string.escape","@popall"],[/./,"string"]],dblStringBody:[[/\\./,{cases:{"@special":"string","@default":"error-token"}}],[/"/,"string.escape","@popall"],[/./,"string"]]}}})); -------------------------------------------------------------------------------- /static/lib/monaco-editor/vs/basic-languages/sb/sb.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * monaco-languages version: 2.1.1(425b0e3c9ea2067410b8f90e0f30de383188c418) 4 | * Released under the MIT license 5 | * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md 6 | *-----------------------------------------------------------------------------*/ 7 | define("vs/basic-languages/sb/sb",["require","exports"],(function(e,o){"use strict";Object.defineProperty(o,"__esModule",{value:!0}),o.language=o.conf=void 0,o.conf={comments:{lineComment:"'"},brackets:[["(",")"],["[","]"],["If","EndIf"],["While","EndWhile"],["For","EndFor"],["Sub","EndSub"]],autoClosingPairs:[{open:'"',close:'"',notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]}]},o.language={defaultToken:"",tokenPostfix:".sb",ignoreCase:!0,brackets:[{token:"delimiter.array",open:"[",close:"]"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"keyword.tag-if",open:"If",close:"EndIf"},{token:"keyword.tag-while",open:"While",close:"EndWhile"},{token:"keyword.tag-for",open:"For",close:"EndFor"},{token:"keyword.tag-sub",open:"Sub",close:"EndSub"}],keywords:["Else","ElseIf","EndFor","EndIf","EndSub","EndWhile","For","Goto","If","Step","Sub","Then","To","While"],tagwords:["If","Sub","While","For"],operators:[">","<","<>","<=",">=","And","Or","+","-","*","/","="],identifier:/[a-zA-Z_][\w]*/,symbols:/[=><:+\-*\/%\.,]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[{include:"@whitespace"},[/(@identifier)(?=[.])/,"type"],[/@identifier/,{cases:{"@keywords":{token:"keyword.$0"},"@operators":"operator","@default":"variable.name"}}],[/([.])(@identifier)/,{cases:{$2:["delimiter","type.member"],"@default":""}}],[/\d*\.\d+/,"number.float"],[/\d+/,"number"],[/[()\[\]]/,"@brackets"],[/@symbols/,{cases:{"@operators":"operator","@default":"delimiter"}}],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"]],whitespace:[[/[ \t\r\n]+/,""],[/(\').*$/,"comment"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"C?/,"string","@pop"]]}}})); -------------------------------------------------------------------------------- /static/lib/monaco-editor/vs/basic-languages/scheme/scheme.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * monaco-languages version: 2.1.1(425b0e3c9ea2067410b8f90e0f30de383188c418) 4 | * Released under the MIT license 5 | * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md 6 | *-----------------------------------------------------------------------------*/ 7 | define("vs/basic-languages/scheme/scheme",["require","exports"],(function(e,o){"use strict";Object.defineProperty(o,"__esModule",{value:!0}),o.language=o.conf=void 0,o.conf={comments:{lineComment:";",blockComment:["#|","|#"]},brackets:[["(",")"],["{","}"],["[","]"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}]},o.language={defaultToken:"",ignoreCase:!0,tokenPostfix:".scheme",brackets:[{open:"(",close:")",token:"delimiter.parenthesis"},{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"}],keywords:["case","do","let","loop","if","else","when","cons","car","cdr","cond","lambda","lambda*","syntax-rules","format","set!","quote","eval","append","list","list?","member?","load"],constants:["#t","#f"],operators:["eq?","eqv?","equal?","and","or","not","null?"],tokenizer:{root:[[/#[xXoObB][0-9a-fA-F]+/,"number.hex"],[/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?/,"number.float"],[/(?:\b(?:(define|define-syntax|define-macro))\b)(\s+)((?:\w|\-|\!|\?)*)/,["keyword","white","variable"]],{include:"@whitespace"},{include:"@strings"},[/[a-zA-Z_#][a-zA-Z0-9_\-\?\!\*]*/,{cases:{"@keywords":"keyword","@constants":"constant","@operators":"operators","@default":"identifier"}}]],comment:[[/[^\|#]+/,"comment"],[/#\|/,"comment","@push"],[/\|#/,"comment","@pop"],[/[\|#]/,"comment"]],whitespace:[[/[ \t\r\n]+/,"white"],[/#\|/,"comment","@comment"],[/;.*$/,"comment"]],strings:[[/"$/,"string","@popall"],[/"(?=.)/,"string","@multiLineString"]],multiLineString:[[/[^\\"]+$/,"string","@popall"],[/[^\\"]+/,"string"],[/\\./,"string.escape"],[/"/,"string","@popall"],[/\\$/,"string"]]}}})); -------------------------------------------------------------------------------- /static/lib/monaco-editor/vs/basic-languages/shell/shell.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * monaco-languages version: 2.1.1(425b0e3c9ea2067410b8f90e0f30de383188c418) 4 | * Released under the MIT license 5 | * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md 6 | *-----------------------------------------------------------------------------*/ 7 | define("vs/basic-languages/shell/shell",["require","exports"],(function(e,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0}),r.language=r.conf=void 0,r.conf={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"`",close:"`"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"`",close:"`"}]},r.language={defaultToken:"",ignoreCase:!0,tokenPostfix:".shell",brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"}],keywords:["if","then","do","else","elif","while","until","for","in","esac","fi","fin","fil","done","exit","set","unset","export","function"],builtins:["ab","awk","bash","beep","cat","cc","cd","chown","chmod","chroot","clear","cp","curl","cut","diff","echo","find","gawk","gcc","get","git","grep","hg","kill","killall","ln","ls","make","mkdir","openssl","mv","nc","node","npm","ping","ps","restart","rm","rmdir","sed","service","sh","shopt","shred","source","sort","sleep","ssh","start","stop","su","sudo","svn","tee","telnet","top","touch","vi","vim","wall","wc","wget","who","write","yes","zsh"],symbols:/[=>"]],autoClosingPairs:[{open:'"',close:'"',notIn:["string","comment"]},{open:"{",close:"}",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]}]},t.language={defaultToken:"",tokenPostfix:".aes",brackets:[{token:"delimiter.curly",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"},{token:"delimiter.angle",open:"<",close:">"}],keywords:["contract","library","entrypoint","function","stateful","state","hash","signature","tuple","list","address","string","bool","int","record","datatype","type","option","oracle","oracle_query","Call","Bits","Bytes","Oracle","String","Crypto","Address","Auth","Chain","None","Some","bits","bytes","event","let","map","private","public","true","false","var","if","else","throw"],operators:["=",">","<","!","~","?","::",":","==","<=",">=","!=","&&","||","++","--","+","-","*","/","&","|","^","%","<<",">>",">>>","+=","-=","*=","/=","&=","|=","^=","%=","<<=",">>=",">>>="],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/,"number.float"],[/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/,"number.float"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/,"number.hex"],[/0[0-7']*[0-7](@integersuffix)/,"number.octal"],[/0[bB][0-1']*[0-1](@integersuffix)/,"number.binary"],[/\d[\d']*\d(@integersuffix)/,"number"],[/\d(@integersuffix)/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@doccomment"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],doccomment:[[/[^\/*]+/,"comment.doc"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]]}}})); -------------------------------------------------------------------------------- /static/lib/monaco-editor/vs/basic-languages/xml/xml.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * monaco-languages version: 2.1.1(425b0e3c9ea2067410b8f90e0f30de383188c418) 4 | * Released under the MIT license 5 | * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md 6 | *-----------------------------------------------------------------------------*/ 7 | define("vs/basic-languages/xml/xml",["require","exports"],(function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.language=t.conf=void 0,t.conf={comments:{blockComment:["\x3c!--","--\x3e"]},brackets:[["<",">"]],autoClosingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],surroundingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}]},t.language={defaultToken:"",tokenPostfix:".xml",ignoreCase:!0,qualifiedName:/(?:[\w\.\-]+:)?[\w\.\-]+/,tokenizer:{root:[[/[^<&]+/,""],{include:"@whitespace"},[/(<)(@qualifiedName)/,[{token:"delimiter"},{token:"tag",next:"@tag"}]],[/(<\/)(@qualifiedName)(\s*)(>)/,[{token:"delimiter"},{token:"tag"},"",{token:"delimiter"}]],[/(<\?)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/(<\!)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/<\!\[CDATA\[/,{token:"delimiter.cdata",next:"@cdata"}],[/&\w+;/,"string.escape"]],cdata:[[/[^\]]+/,""],[/\]\]>/,{token:"delimiter.cdata",next:"@pop"}],[/\]/,""]],tag:[[/[ \t\r\n]+/,""],[/(@qualifiedName)(\s*=\s*)("[^"]*"|'[^']*')/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">?\/]*|'[^'>?\/]*)(?=[\?\/]\>)/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">]*|'[^'>]*)/,["attribute.name","","attribute.value"]],[/@qualifiedName/,"attribute.name"],[/\?>/,{token:"delimiter",next:"@pop"}],[/(\/)(>)/,[{token:"tag"},{token:"delimiter",next:"@pop"}]],[/>/,{token:"delimiter",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[//,{token:"comment",next:"@pop"}],[/ 71 |
-------------------------------------------------------------------------------- /views/page.ejs: -------------------------------------------------------------------------------- 1 | <%- include('header', { template: 'article' }) %> 2 | 3 |
4 | 5 | <% if (article && article.breadcrumb && article.breadcrumb.length) { %> 6 | 14 | <% } %> 15 | 16 |
17 |
18 | <%- article.content %> 19 |
20 |
21 |
22 | 23 | <%- include('footer') %> -------------------------------------------------------------------------------- /views/pagination.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | if (typeof page !== 'undefined' && typeof max_page !== 'undefined' && page && max_page && max_page > 1) { 3 | let pageSet = new Set(); 4 | for (let i = 1; i <= 3 && i <= max_page; i++) { 5 | pageSet.add(i); 6 | } 7 | for (let i = max_page; i > max_page - 3 && i >= 1; i--) { 8 | pageSet.add(i); 9 | } 10 | for (let i = page - 1; i <= page + 1; i++) 11 | if (1 <= i && i <= max_page) { 12 | pageSet.add(i); 13 | } 14 | %> 15 |
16 | 39 |
40 | 41 | <% 42 | } 43 | %> -------------------------------------------------------------------------------- /views/timeline.ejs: -------------------------------------------------------------------------------- 1 | <%- include('header', { template: 'timeline' }) %> 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | <% for (article of articles) { %> 14 | 15 | 18 | 24 | 27 | 35 | 36 | <% } %> 37 | 38 |
分类标题发布时间标签
16 | <%= article.uri.split('/')[1] %> 17 | 19 | <%= article.title %> 20 | <% if (article.link) { %> 21 | 22 | <% } %> 23 | 25 | <%= article.date.format('YYYY年MM月DD日 HH:mm') %> 26 | 28 | <% if (article.tag) article.tag.forEach(tag => { %> 29 | 33 | <% }); %> 34 |
39 | 40 | 43 | 44 | <%- include('footer') %> -------------------------------------------------------------------------------- /views/todolist.ejs: -------------------------------------------------------------------------------- 1 | <%- include('header', { template: 'todolist' }) %> 2 | 3 | <% function render(item) { %> 4 |
5 | 6 | <%= item.title %> 7 | <% if (item.link) { %> 8 | 9 | <% } %> 10 |
11 |
12 | <%- item.description.map(e => '

' + e + '

').join('') %> 13 | <%- item.preview %> 14 | <% if (item.children.length) { %> 15 |
> 16 | <% item.children.forEach(child => render(child)) %> 17 |
18 | <% } %> 19 |
20 | <% } %> 21 | 22 |
23 |
24 | <%= todo.title %> 25 |
26 |
27 | <% todo.children.forEach(child => render(child)) %> 28 |
29 |
30 | 31 | 36 | 37 | <%- include('footer') %> --------------------------------------------------------------------------------