first commit
This commit is contained in:
318
.gitignore
vendored
Normal file
318
.gitignore
vendored
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
_*/
|
||||||
|
dist-newstyle/
|
||||||
|
site
|
||||||
|
.ds_store
|
||||||
|
.vscode/
|
||||||
|
*.sage.py
|
||||||
|
*.pdf
|
||||||
|
main.md
|
||||||
|
images/*
|
||||||
|
ref.bib
|
||||||
|
## Core latex/pdflatex auxiliary files:
|
||||||
|
*.aux
|
||||||
|
*.lof
|
||||||
|
*.log
|
||||||
|
*.lot
|
||||||
|
*.fls
|
||||||
|
*.out
|
||||||
|
*.toc
|
||||||
|
*.fmt
|
||||||
|
*.fot
|
||||||
|
*.cb
|
||||||
|
*.cb2
|
||||||
|
.*.lb
|
||||||
|
|
||||||
|
## Intermediate documents:
|
||||||
|
*.dvi
|
||||||
|
*.xdv
|
||||||
|
*-converted-to.*
|
||||||
|
# these rules might exclude image files for figures etc.
|
||||||
|
# *.ps
|
||||||
|
# *.eps
|
||||||
|
# *.pdf
|
||||||
|
|
||||||
|
## Generated if empty string is given at "Please type another file name for output:"
|
||||||
|
.pdf
|
||||||
|
|
||||||
|
## Bibliography auxiliary files (bibtex/biblatex/biber):
|
||||||
|
*.bbl
|
||||||
|
*.bbl-SAVE-ERROR
|
||||||
|
*.bcf
|
||||||
|
*.bcf-SAVE-ERROR
|
||||||
|
*.blg
|
||||||
|
*-blx.aux
|
||||||
|
*-blx.bib
|
||||||
|
*.run.xml
|
||||||
|
|
||||||
|
## Build tool auxiliary files:
|
||||||
|
*.fdb_latexmk
|
||||||
|
*.synctex
|
||||||
|
*.synctex(busy)
|
||||||
|
*.synctex.gz
|
||||||
|
*.synctex.gz(busy)
|
||||||
|
*.pdfsync
|
||||||
|
*.rubbercache
|
||||||
|
rubber.cache
|
||||||
|
|
||||||
|
## Build tool directories for auxiliary files
|
||||||
|
# latexrun
|
||||||
|
latex.out/
|
||||||
|
|
||||||
|
## Auxiliary and intermediate files from other packages:
|
||||||
|
# algorithms
|
||||||
|
*.alg
|
||||||
|
*.loa
|
||||||
|
|
||||||
|
# achemso
|
||||||
|
acs-*.bib
|
||||||
|
|
||||||
|
# amsthm
|
||||||
|
*.thm
|
||||||
|
|
||||||
|
# beamer
|
||||||
|
*.nav
|
||||||
|
*.pre
|
||||||
|
*.snm
|
||||||
|
*.vrb
|
||||||
|
|
||||||
|
# changes
|
||||||
|
*.soc
|
||||||
|
|
||||||
|
# comment
|
||||||
|
*.cut
|
||||||
|
|
||||||
|
# cprotect
|
||||||
|
*.cpt
|
||||||
|
|
||||||
|
# elsarticle (documentclass of Elsevier journals)
|
||||||
|
*.spl
|
||||||
|
|
||||||
|
# endnotes
|
||||||
|
*.ent
|
||||||
|
|
||||||
|
# fixme
|
||||||
|
*.lox
|
||||||
|
|
||||||
|
# feynmf/feynmp
|
||||||
|
*.mf
|
||||||
|
*.mp
|
||||||
|
*.t[1-9]
|
||||||
|
*.t[1-9][0-9]
|
||||||
|
*.tfm
|
||||||
|
|
||||||
|
#(r)(e)ledmac/(r)(e)ledpar
|
||||||
|
*.end
|
||||||
|
*.?end
|
||||||
|
*.[1-9]
|
||||||
|
*.[1-9][0-9]
|
||||||
|
*.[1-9][0-9][0-9]
|
||||||
|
*.[1-9]R
|
||||||
|
*.[1-9][0-9]R
|
||||||
|
*.[1-9][0-9][0-9]R
|
||||||
|
*.eledsec[1-9]
|
||||||
|
*.eledsec[1-9]R
|
||||||
|
*.eledsec[1-9][0-9]
|
||||||
|
*.eledsec[1-9][0-9]R
|
||||||
|
*.eledsec[1-9][0-9][0-9]
|
||||||
|
*.eledsec[1-9][0-9][0-9]R
|
||||||
|
|
||||||
|
# glossaries
|
||||||
|
*.acn
|
||||||
|
*.acr
|
||||||
|
*.glg
|
||||||
|
*.glo
|
||||||
|
*.gls
|
||||||
|
*.glsdefs
|
||||||
|
*.lzo
|
||||||
|
*.lzs
|
||||||
|
*.slg
|
||||||
|
*.slo
|
||||||
|
*.sls
|
||||||
|
|
||||||
|
# uncomment this for glossaries-extra (will ignore makeindex's style files!)
|
||||||
|
# *.ist
|
||||||
|
|
||||||
|
# gnuplot
|
||||||
|
*.gnuplot
|
||||||
|
*.table
|
||||||
|
|
||||||
|
# gnuplottex
|
||||||
|
*-gnuplottex-*
|
||||||
|
|
||||||
|
# gregoriotex
|
||||||
|
*.gaux
|
||||||
|
*.glog
|
||||||
|
*.gtex
|
||||||
|
|
||||||
|
# htlatex
|
||||||
|
*.4ct
|
||||||
|
*.4tc
|
||||||
|
*.idv
|
||||||
|
*.lg
|
||||||
|
*.trc
|
||||||
|
*.xref
|
||||||
|
|
||||||
|
# hypdoc
|
||||||
|
*.hd
|
||||||
|
|
||||||
|
# hyperref
|
||||||
|
*.brf
|
||||||
|
|
||||||
|
# knitr
|
||||||
|
*-concordance.tex
|
||||||
|
# TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files
|
||||||
|
# *.tikz
|
||||||
|
*-tikzDictionary
|
||||||
|
|
||||||
|
# listings
|
||||||
|
*.lol
|
||||||
|
|
||||||
|
# luatexja-ruby
|
||||||
|
*.ltjruby
|
||||||
|
|
||||||
|
# makeidx
|
||||||
|
*.idx
|
||||||
|
*.ilg
|
||||||
|
*.ind
|
||||||
|
|
||||||
|
# minitoc
|
||||||
|
*.maf
|
||||||
|
*.mlf
|
||||||
|
*.mlt
|
||||||
|
*.mtc[0-9]*
|
||||||
|
*.slf[0-9]*
|
||||||
|
*.slt[0-9]*
|
||||||
|
*.stc[0-9]*
|
||||||
|
|
||||||
|
# minted
|
||||||
|
_minted*
|
||||||
|
*.pyg
|
||||||
|
|
||||||
|
# morewrites
|
||||||
|
*.mw
|
||||||
|
|
||||||
|
# newpax
|
||||||
|
*.newpax
|
||||||
|
|
||||||
|
# nomencl
|
||||||
|
*.nlg
|
||||||
|
*.nlo
|
||||||
|
*.nls
|
||||||
|
|
||||||
|
# pax
|
||||||
|
*.pax
|
||||||
|
|
||||||
|
# pdfpcnotes
|
||||||
|
*.pdfpc
|
||||||
|
|
||||||
|
# sagetex
|
||||||
|
*.sagetex.sage
|
||||||
|
*.sagetex.py
|
||||||
|
*.sagetex.scmd
|
||||||
|
|
||||||
|
# scrwfile
|
||||||
|
*.wrt
|
||||||
|
|
||||||
|
# svg
|
||||||
|
svg-inkscape/
|
||||||
|
|
||||||
|
# sympy
|
||||||
|
*.sout
|
||||||
|
*.sympy
|
||||||
|
sympy-plots-for-*.tex/
|
||||||
|
|
||||||
|
# pdfcomment
|
||||||
|
*.upa
|
||||||
|
*.upb
|
||||||
|
|
||||||
|
# pythontex
|
||||||
|
*.pytxcode
|
||||||
|
pythontex-files-*/
|
||||||
|
|
||||||
|
# tcolorbox
|
||||||
|
*.listing
|
||||||
|
|
||||||
|
# thmtools
|
||||||
|
*.loe
|
||||||
|
|
||||||
|
# TikZ & PGF
|
||||||
|
*.dpth
|
||||||
|
*.md5
|
||||||
|
*.auxlock
|
||||||
|
|
||||||
|
# titletoc
|
||||||
|
*.ptc
|
||||||
|
|
||||||
|
# todonotes
|
||||||
|
*.tdo
|
||||||
|
|
||||||
|
# vhistory
|
||||||
|
*.hst
|
||||||
|
*.ver
|
||||||
|
|
||||||
|
# easy-todo
|
||||||
|
*.lod
|
||||||
|
|
||||||
|
# xcolor
|
||||||
|
*.xcp
|
||||||
|
|
||||||
|
# xmpincl
|
||||||
|
*.xmpi
|
||||||
|
|
||||||
|
# xindy
|
||||||
|
*.xdy
|
||||||
|
|
||||||
|
# xypic precompiled matrices and outlines
|
||||||
|
*.xyc
|
||||||
|
*.xyd
|
||||||
|
|
||||||
|
# endfloat
|
||||||
|
*.ttt
|
||||||
|
*.fff
|
||||||
|
|
||||||
|
# Latexian
|
||||||
|
TSWLatexianTemp*
|
||||||
|
|
||||||
|
## Editors:
|
||||||
|
# WinEdt
|
||||||
|
*.bak
|
||||||
|
*.sav
|
||||||
|
|
||||||
|
# Texpad
|
||||||
|
.texpadtmp
|
||||||
|
|
||||||
|
# LyX
|
||||||
|
*.lyx~
|
||||||
|
|
||||||
|
# Kile
|
||||||
|
*.backup
|
||||||
|
|
||||||
|
# gummi
|
||||||
|
.*.swp
|
||||||
|
|
||||||
|
# KBibTeX
|
||||||
|
*~[0-9]*
|
||||||
|
|
||||||
|
# TeXnicCenter
|
||||||
|
*.tps
|
||||||
|
|
||||||
|
# auto folder when using emacs and auctex
|
||||||
|
./auto/*
|
||||||
|
*.el
|
||||||
|
|
||||||
|
# expex forward references with \gathertags
|
||||||
|
*-tags.tex
|
||||||
|
|
||||||
|
# standalone packages
|
||||||
|
*.sta
|
||||||
|
|
||||||
|
# Makeindex log files
|
||||||
|
*.lpz
|
||||||
|
|
||||||
|
# xwatermark package
|
||||||
|
*.xwm
|
||||||
|
|
||||||
|
# REVTeX puts footnotes in the bibliography by default, unless the nofootinbib
|
||||||
|
# option is specified. Footnotes are the stored in a file with suffix Notes.bib.
|
||||||
|
# Uncomment the next line to have this generated file ignored.
|
||||||
|
#*Notes.bib
|
||||||
130
assets/bib_style.csl
Normal file
130
assets/bib_style.csl
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only" default-locale="en-US">
|
||||||
|
<!-- This style was edited with the Visual CSL Editor (http://editor.citationstyles.org/visualEditor/) -->
|
||||||
|
<info>
|
||||||
|
<title>Elsevier (numeric, with titles)</title>
|
||||||
|
<id>http://www.zotero.org/styles/elsevier-numeric-with-titles</id>
|
||||||
|
<link href="http://www.zotero.org/styles/elsevier-numeric-with-titles" rel="self"/>
|
||||||
|
<link href="http://www.zotero.org/styles/elsevier-without-titles" rel="template"/>
|
||||||
|
<link href="http://www.elsevier.com/journals/solid-state-electronics/0038-1101/guide-for-authors#68000" rel="documentation"/>
|
||||||
|
<author>
|
||||||
|
<name>Richard Karnesky</name>
|
||||||
|
<email>karnesky+zotero@gmail.com</email>
|
||||||
|
<uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>
|
||||||
|
</author>
|
||||||
|
<contributor>
|
||||||
|
<name>Rintze Zelle</name>
|
||||||
|
<uri>http://twitter.com/rintzezelle</uri>
|
||||||
|
</contributor>
|
||||||
|
<category citation-format="numeric"/>
|
||||||
|
<category field="generic-base"/>
|
||||||
|
<summary>A style for many of Elsevier's journals that includes article titles in the reference list</summary>
|
||||||
|
<updated>2025-06-05T07:59:51+00:00</updated>
|
||||||
|
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
|
||||||
|
</info>
|
||||||
|
<macro name="author">
|
||||||
|
<names variable="author">
|
||||||
|
<name initialize-with="." delimiter=", " delimiter-precedes-last="always"/>
|
||||||
|
<label form="short" prefix=", "/>
|
||||||
|
<substitute>
|
||||||
|
<names variable="editor"/>
|
||||||
|
<names variable="translator"/>
|
||||||
|
</substitute>
|
||||||
|
</names>
|
||||||
|
</macro>
|
||||||
|
<macro name="editor">
|
||||||
|
<names variable="editor">
|
||||||
|
<name initialize-with="." delimiter=", " delimiter-precedes-last="always"/>
|
||||||
|
<label form="short" prefix=" (" text-case="capitalize-first" suffix=".)" strip-periods="true"/>
|
||||||
|
</names>
|
||||||
|
</macro>
|
||||||
|
<macro name="year-date">
|
||||||
|
<choose>
|
||||||
|
<if variable="issued">
|
||||||
|
<date variable="issued">
|
||||||
|
<date-part name="year"/>
|
||||||
|
</date>
|
||||||
|
</if>
|
||||||
|
<else>
|
||||||
|
<text term="no date" form="short"/>
|
||||||
|
</else>
|
||||||
|
</choose>
|
||||||
|
</macro>
|
||||||
|
<macro name="publisher">
|
||||||
|
<text variable="publisher" suffix=", "/>
|
||||||
|
<text variable="publisher-place" suffix=", "/>
|
||||||
|
<text macro="year-date"/>
|
||||||
|
</macro>
|
||||||
|
<macro name="edition">
|
||||||
|
<choose>
|
||||||
|
<if is-numeric="edition">
|
||||||
|
<group delimiter=" ">
|
||||||
|
<number variable="edition" form="ordinal"/>
|
||||||
|
<text term="edition" form="short"/>
|
||||||
|
</group>
|
||||||
|
</if>
|
||||||
|
<else>
|
||||||
|
<text variable="edition"/>
|
||||||
|
</else>
|
||||||
|
</choose>
|
||||||
|
</macro>
|
||||||
|
<citation collapse="citation-number">
|
||||||
|
<sort>
|
||||||
|
<key variable="citation-number"/>
|
||||||
|
</sort>
|
||||||
|
<layout prefix="[" suffix="]" delimiter=",">
|
||||||
|
<text variable="citation-number"/>
|
||||||
|
</layout>
|
||||||
|
</citation>
|
||||||
|
<bibliography entry-spacing="0" second-field-align="flush" et-al-min="7" et-al-use-first="6">
|
||||||
|
<layout suffix=".">
|
||||||
|
<text variable="citation-number" prefix="[" suffix="]"/>
|
||||||
|
<text macro="author" prefix=" " suffix=", "/>
|
||||||
|
<choose>
|
||||||
|
<if type="bill book graphic legal_case legislation motion_picture report song" match="any">
|
||||||
|
<group delimiter=", ">
|
||||||
|
<text variable="title" font-style="normal" font-weight="normal"/>
|
||||||
|
<text macro="edition"/>
|
||||||
|
<text macro="publisher"/>
|
||||||
|
</group>
|
||||||
|
</if>
|
||||||
|
<else-if type="chapter paper-conference" match="any">
|
||||||
|
<text variable="title" suffix=", "/>
|
||||||
|
<text term="in" suffix=": "/>
|
||||||
|
<text variable="container-title" form="short" text-case="title" font-style="italic" suffix=", "/>
|
||||||
|
<text macro="edition" suffix=", "/>
|
||||||
|
<text macro="publisher"/>
|
||||||
|
<group delimiter=" ">
|
||||||
|
<label variable="page" form="short" prefix=": "/>
|
||||||
|
<text variable="page"/>
|
||||||
|
</group>
|
||||||
|
</else-if>
|
||||||
|
<else-if type="patent">
|
||||||
|
<group delimiter=", ">
|
||||||
|
<text variable="title"/>
|
||||||
|
<text variable="number"/>
|
||||||
|
<text macro="year-date"/>
|
||||||
|
</group>
|
||||||
|
</else-if>
|
||||||
|
<else-if type="thesis">
|
||||||
|
<group delimiter=", ">
|
||||||
|
<text variable="title"/>
|
||||||
|
<text variable="genre"/>
|
||||||
|
<text variable="publisher"/>
|
||||||
|
<text macro="year-date"/>
|
||||||
|
</group>
|
||||||
|
</else-if>
|
||||||
|
<else>
|
||||||
|
<group delimiter=" ">
|
||||||
|
<text variable="title" font-style="normal" font-weight="normal" suffix=","/>
|
||||||
|
<text variable="container-title" form="short" text-case="title" font-style="italic" suffix="."/>
|
||||||
|
<text variable="volume"/>
|
||||||
|
<text macro="year-date" prefix="(" suffix=")"/>
|
||||||
|
<text variable="page" form="short"/>
|
||||||
|
</group>
|
||||||
|
</else>
|
||||||
|
</choose>
|
||||||
|
<text variable="DOI" prefix=" "/>
|
||||||
|
</layout>
|
||||||
|
</bibliography>
|
||||||
|
</style>
|
||||||
100
assets/css/chao-theorems.css
Normal file
100
assets/css/chao-theorems.css
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
.theorem-environment {
|
||||||
|
font-style: italic;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theorem-header {
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theorem-header .index:before {
|
||||||
|
content: ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
.theorem-header .name:before {
|
||||||
|
content: ' (';
|
||||||
|
}
|
||||||
|
|
||||||
|
.theorem-header .name:after {
|
||||||
|
content: ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
.theorem-header:after {
|
||||||
|
content: '.\2002\2002';
|
||||||
|
}
|
||||||
|
|
||||||
|
.theorem-header+p {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Proof .type {
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Proof {
|
||||||
|
font-style: normal;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Proof:after {
|
||||||
|
content: '∎';
|
||||||
|
position: absolute;
|
||||||
|
right: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Proof span.theorem-header span.name {
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Proof span.theorem-header span.name:before {
|
||||||
|
content: ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
.Proof span.theorem-header span.name:after {
|
||||||
|
content: ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
table.postindex {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.postindex cite {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.postindex td.right {
|
||||||
|
text-align: right;
|
||||||
|
width: 11ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-section-number {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-section-number:after {
|
||||||
|
content: '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
.csl-entry {
|
||||||
|
display: table;
|
||||||
|
width: 100%;
|
||||||
|
table-layout: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.csl-left-margin {
|
||||||
|
display: table-cell;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.csl-right-inline {
|
||||||
|
display: table-cell;
|
||||||
|
}
|
||||||
|
.csl-right-inline a{
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
380
assets/css/default.css
Normal file
380
assets/css/default.css
Normal file
@@ -0,0 +1,380 @@
|
|||||||
|
:root {
|
||||||
|
--color-text: black;
|
||||||
|
--color-tag1: gray;
|
||||||
|
--color-tag2: darkolivegreen;
|
||||||
|
--color-bg: white;
|
||||||
|
--color-notice: #fb4f4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scrollbar-gutter: stable;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
font-size: 110%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Lato', -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-optical-sizing: auto;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 140%;
|
||||||
|
color: var(--color-text);
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
body a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
details {
|
||||||
|
padding-left: 1em;
|
||||||
|
border: 2px solid var(--color-text);
|
||||||
|
}
|
||||||
|
summary:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*mathML*/
|
||||||
|
.htmlmathparagraph, mtext,math {
|
||||||
|
font-family: Lete Sans Math;
|
||||||
|
}
|
||||||
|
.math-container,
|
||||||
|
#math-container {
|
||||||
|
display: block;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
padding: .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.equation {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
align-items: center;
|
||||||
|
column-gap: 1em;
|
||||||
|
margin: .5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.equation .math-container {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.equation-number {
|
||||||
|
white-space: nowrap;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-space .langtag {
|
||||||
|
color: var(--color-tag1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sc {
|
||||||
|
font-variant-caps: small-caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.url {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
html body div.text-space main ul.post-list {
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* top bar */
|
||||||
|
header {
|
||||||
|
font-weight: 400;
|
||||||
|
font-family: "IosevkaC", sans-serif;
|
||||||
|
}
|
||||||
|
nav a {
|
||||||
|
display: inline-block;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uri {
|
||||||
|
word-wrap: break-word;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
color: var(--color-text);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
margin-top: 2em;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagetitle {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
text-align: left;
|
||||||
|
line-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-top: 1em;
|
||||||
|
font-size: 1.44rem;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 1em;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-top: 1em;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal
|
||||||
|
}
|
||||||
|
|
||||||
|
article .header {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-style: normal;
|
||||||
|
color: var(--color-tag1);
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.info,.info a {
|
||||||
|
color: var(--color-tag2);
|
||||||
|
font-size: 1rem;
|
||||||
|
font-style: normal;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info a:visited {
|
||||||
|
color: var(--color-tag2);
|
||||||
|
}
|
||||||
|
|
||||||
|
section.body {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ascii-art {
|
||||||
|
font-family: monospace;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* table. copied from https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/table */
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border: 2px solid rgb(140 140 140);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
caption {
|
||||||
|
caption-side: bottom;
|
||||||
|
padding: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead,
|
||||||
|
tfoot {
|
||||||
|
background-color: rgb(228 240 245);
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
border: 1px solid rgb(160 160 160);
|
||||||
|
padding: 8px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:last-of-type {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody > tr:nth-of-type(even) {
|
||||||
|
background-color: rgb(237 238 242);
|
||||||
|
}
|
||||||
|
|
||||||
|
tfoot th {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
tfoot td {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
figure {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
padding: 5px;
|
||||||
|
margin: auto;
|
||||||
|
max-width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerimg img {
|
||||||
|
margin: 0 auto 0 auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.highlight,
|
||||||
|
pre code {
|
||||||
|
margin: auto;
|
||||||
|
padding: 10px;
|
||||||
|
overflow: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: "IosevkaC", monospace;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0px 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-variant-ligatures: none;
|
||||||
|
font-kerning: none;
|
||||||
|
text-rendering: optimizeSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.draft-notice {
|
||||||
|
color: var(--color-notice);
|
||||||
|
margin: 1em auto;
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-top: 0
|
||||||
|
}
|
||||||
|
.gallery {
|
||||||
|
margin-top: 2em;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery img {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 320px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* phones -- no sidebar no sidenotes*/
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
body {
|
||||||
|
/* width: 90%; */
|
||||||
|
margin: auto;
|
||||||
|
padding: 0 5%;
|
||||||
|
text-align: left;
|
||||||
|
max-width: 876px;
|
||||||
|
}
|
||||||
|
mjx-container[display="true"]
|
||||||
|
/*, .katex-display */ {
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .katex-display>.katex>.katex-html>.tag {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 10pt;
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sidebar. no sidenotes */
|
||||||
|
@media (min-width: 769px) {
|
||||||
|
body {
|
||||||
|
max-width: 1350px;
|
||||||
|
display: -webkit-flex;
|
||||||
|
-webkit-flex-flow: row wrap;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
-ms-flex-flow: row wrap;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
width: 95%;
|
||||||
|
padding-right: 5%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc {
|
||||||
|
margin-top: 5rem;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
width: 33%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#contents ul,
|
||||||
|
div#contents-big ul {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
padding-left: 1em;
|
||||||
|
line-height: 1.2;
|
||||||
|
list-style-type: decimal;
|
||||||
|
margin-left: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
div#contents-big ul ul {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#contents-big li+li {
|
||||||
|
margin-top: 0.5em
|
||||||
|
}
|
||||||
|
|
||||||
|
div#contents-big {
|
||||||
|
font-size: 80%;
|
||||||
|
padding-top: 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
text-align: left;
|
||||||
|
max-width: 60%;
|
||||||
|
clear: both;
|
||||||
|
margin-right: 4em;
|
||||||
|
position: sticky;
|
||||||
|
top: 5rem;
|
||||||
|
left: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
div#contents-big .mini-header {
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
font-variant: small-caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-space {
|
||||||
|
display: inline-block;
|
||||||
|
width: 66%;
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* sidebar+sidenotes */
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
body {
|
||||||
|
width: 75%;
|
||||||
|
padding-right: 25%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
|
||||||
|
.no-print,
|
||||||
|
.no-print * {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
52
assets/css/fonts.css
Normal file
52
assets/css/fonts.css
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
/* fonts */
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Lato";
|
||||||
|
src: url("/fonts/Lato-Regular.woff2") format("woff2");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "Lato";
|
||||||
|
src: url("/fonts/Lato-Bold.woff2") format("woff2");
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "Lato";
|
||||||
|
src: url("/fonts/Lato-Italic.woff2") format("woff2");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "Lato";
|
||||||
|
src: url("/fonts/Lato-BoldItalic.woff2") format("woff2");
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "Lete Sans Math";
|
||||||
|
src: url("/fonts/LeteSansMath.woff2") format("woff2");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "Lete Sans Math";
|
||||||
|
src: url("/fonts/LeteSansMath-Bold.woff2") format("woff2");
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "IosevkaC";
|
||||||
|
src: url("/fonts/IosevkaCustom-Regular.woff2") format("woff2");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "IosevkaC";
|
||||||
|
src: url("/fonts/IosevkaCustom-Bold.woff2") format("woff2");
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
35
assets/css/pygentize.css
Normal file
35
assets/css/pygentize.css
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
code.sourceCode
|
||||||
|
{
|
||||||
|
background: inherit
|
||||||
|
}
|
||||||
|
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
|
||||||
|
code span.al { color: #CB4B16; font-weight: bold; } /* Alert */
|
||||||
|
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
|
||||||
|
code span.at { color: #7d9029; } /* Attribute */
|
||||||
|
code span.bn { color: #D33682; } /* BaseN */
|
||||||
|
code span.bu { } /* BuiltIn */
|
||||||
|
code span.cf { color: #5F8700; font-weight: bold; } /* ControlFlow */
|
||||||
|
code span.ch { color: #16801a; } /* Char */
|
||||||
|
code span.cn { color: #880000; } /* Constant */
|
||||||
|
code span.co { color: #93A1A1; font-style: italic; } /* Comment */
|
||||||
|
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
|
||||||
|
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
|
||||||
|
code span.dt { background-color: #f8edff; } /* DataType */
|
||||||
|
code span.dv { color: #D33682; } /* DecVal */
|
||||||
|
code span.er { color: #D30102; font-weight: bold; } /* Error */
|
||||||
|
code span.ex { } /* Extension */
|
||||||
|
code span.fl { color: #D33682; } /* Float */
|
||||||
|
code span.fu { } /* Function */
|
||||||
|
code span.im { color: #D70000} /* Import */
|
||||||
|
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
|
||||||
|
code span.kw { font-weight: bold; } /* Keyword */
|
||||||
|
code span.op { font-weight: bold; } /* Operator */
|
||||||
|
code span.ot { font-weight: bold; } /* Other */
|
||||||
|
code span.pp { color: #bc7a00; } /* Preprocessor */
|
||||||
|
code span.sc { color: #4070a0; } /* SpecialChar */
|
||||||
|
code span.ss { color: #bb6688; } /* SpecialString */
|
||||||
|
code span.st { color: #16801a; } /* String */
|
||||||
|
code span.va { color: #19177c; } /* Variable */
|
||||||
|
code span.vs { color: #4070a0; } /* VerbatimString */
|
||||||
|
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
|
||||||
179
assets/css/sidenotes.css
Normal file
179
assets/css/sidenotes.css
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
This file is copied from
|
||||||
|
https://github.com/slotThe/slotThe.github.io/blob/main/css/sidenotes.css
|
||||||
|
with minor modifications made by Yu Cong.
|
||||||
|
|
||||||
|
The original author is Tony Zorman.
|
||||||
|
|
||||||
|
Extracted from:
|
||||||
|
|
||||||
|
https://github.com/edwardtufte/tufte-css
|
||||||
|
|
||||||
|
and modified to fit my website's theme.
|
||||||
|
*/
|
||||||
|
|
||||||
|
body {
|
||||||
|
counter-reset: sidenote-counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidenote,
|
||||||
|
.marginnote,
|
||||||
|
.marginnote-left {
|
||||||
|
float: right;
|
||||||
|
clear: right;
|
||||||
|
margin-right: -45%;
|
||||||
|
width: 40%;
|
||||||
|
margin-top: 0.3rem;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 0.8em;
|
||||||
|
line-height: 1.2;
|
||||||
|
vertical-align: baseline;
|
||||||
|
position: relative;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.sidenote,
|
||||||
|
.marginnote,
|
||||||
|
.marginnote-left {
|
||||||
|
margin-right: -40%;
|
||||||
|
width: 33%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.marginnote-left {
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
margin-left: -32%;
|
||||||
|
width: 25%;
|
||||||
|
position: relative;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
/* The first condition is for the case of a left-aligned layout (on a
|
||||||
|
smaller screen), and the second condition for a more centered layout
|
||||||
|
on a larger screen. It's a bit awkward, sadly :/ */
|
||||||
|
@media (max-width: 1349px) or ((min-width: 1367px) and (max-width: 1620px)) {
|
||||||
|
.marginnote-left {
|
||||||
|
margin-left: -33%;
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidenote code {
|
||||||
|
font-size: 0.94em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For some reason, although only `overflow-x` is set in `default.css`,
|
||||||
|
block code in side and marginnotes gets a vertical (!) scrollbar no
|
||||||
|
matter what; disable that.
|
||||||
|
*/
|
||||||
|
div .marginnote pre,
|
||||||
|
div .sidenote pre {
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidenote-number {
|
||||||
|
counter-increment: sidenote-counter;
|
||||||
|
color: var(--color-link);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidenote-number:after,
|
||||||
|
.sidenote:before {
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidenote-number:after {
|
||||||
|
content: counter(sidenote-counter);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
top: -0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Properly position siednote number and adjust position of sidenote
|
||||||
|
paragraphs:
|
||||||
|
https://github.com/edwardtufte/tufte-css/issues/93#issuecomment-670695382
|
||||||
|
*/
|
||||||
|
.sidenote::before {
|
||||||
|
content: counter(sidenote-counter) " ";
|
||||||
|
font-size: 0.8rem;
|
||||||
|
top: -0.55rem;
|
||||||
|
position: absolute;
|
||||||
|
right: calc(100% + 0.5em);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidenote p {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidenote p:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidenote p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
input.margin-toggle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
label.sidenote-number {
|
||||||
|
display: inline-block;
|
||||||
|
max-height: 2rem; /* should be less than or equal to paragraph line-height */
|
||||||
|
}
|
||||||
|
|
||||||
|
label.margin-toggle:not(.sidenote-number) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iframe-wrapper {
|
||||||
|
position: relative;
|
||||||
|
padding-bottom: 56.25%; /* 16:9 */
|
||||||
|
padding-top: 25px;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iframe-wrapper iframe {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
label.margin-toggle:not(.sidenote-number) {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidenote,
|
||||||
|
.marginnote,
|
||||||
|
.marginnote-left {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Linkify sidenotes iff they are clickable */
|
||||||
|
.margin-toggle,
|
||||||
|
.sidenote-number:after {
|
||||||
|
color: var(--color-link);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-toggle:checked + .sidenote,
|
||||||
|
.margin-toggle:checked + .marginnote,
|
||||||
|
.margin-toggle:checked + .marginnote-left {
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
left: 1rem;
|
||||||
|
clear: both;
|
||||||
|
width: 95%;
|
||||||
|
margin: 1rem 2.5%;
|
||||||
|
position: relative;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/favicon.ico
Normal file
BIN
assets/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
BIN
assets/fonts/IosevkaCustom-Bold.woff2
Normal file
BIN
assets/fonts/IosevkaCustom-Bold.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/IosevkaCustom-Italic.woff2
Normal file
BIN
assets/fonts/IosevkaCustom-Italic.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/IosevkaCustom-Regular.woff2
Normal file
BIN
assets/fonts/IosevkaCustom-Regular.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/Lato-Bold.woff2
Normal file
BIN
assets/fonts/Lato-Bold.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/Lato-BoldItalic.woff2
Normal file
BIN
assets/fonts/Lato-BoldItalic.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/Lato-Italic.woff2
Normal file
BIN
assets/fonts/Lato-Italic.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/Lato-Regular.woff2
Normal file
BIN
assets/fonts/Lato-Regular.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/LeteSansMath-Bold.otf
Normal file
BIN
assets/fonts/LeteSansMath-Bold.otf
Normal file
Binary file not shown.
BIN
assets/fonts/LeteSansMath-Bold.woff2
Normal file
BIN
assets/fonts/LeteSansMath-Bold.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/LeteSansMath.otf
Normal file
BIN
assets/fonts/LeteSansMath.otf
Normal file
Binary file not shown.
BIN
assets/fonts/LeteSansMath.woff2
Normal file
BIN
assets/fonts/LeteSansMath.woff2
Normal file
Binary file not shown.
22
assets/math-macros.tex
Normal file
22
assets/math-macros.tex
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
\newcommand{\F}{\mathcal{F}}
|
||||||
|
\newcommand{\B}{\mathcal{B}}
|
||||||
|
\newcommand{\I}{\mathcal{I}}
|
||||||
|
\newcommand{\C}{\mathcal{C}}
|
||||||
|
\newcommand{\Hit}{\text{Hit}}
|
||||||
|
\newcommand{\HSGap}{\text{HSGap}}
|
||||||
|
\newcommand{\IntGap}{\text{IntGap}}
|
||||||
|
\newcommand{\OPTLP}{\text{OPTLP}}
|
||||||
|
\newcommand{\OPT}{\text{OPT}}
|
||||||
|
\newcommand{\DecRank}{\text{Rank-}k\text{-Reduction}}
|
||||||
|
\newcommand{\flats}{\operatorname{Flats}}
|
||||||
|
\newcommand{\cl}{\operatorname{cl}}
|
||||||
|
\newcommand{\gap}{\operatorname{gap}}
|
||||||
|
\newcommand{\igap}{\operatorname{igap}}
|
||||||
|
\newcommand{\cogirthratio}{\rho}
|
||||||
|
\newcommand{\cogirthratiowt}{\cogirthratio^{\mathrm{wt}}}
|
||||||
|
\newcommand{\strength}{\operatorname{strength}}
|
||||||
|
\newcommand{\argmin}{\operatorname{arg\,min}}
|
||||||
|
\newcommand{\argmax}{\operatorname{arg\,max}}
|
||||||
|
\newcommand{\del}{\setminus}
|
||||||
|
\newcommand{\con}{/}
|
||||||
|
\newcommand{\minor}{\times}
|
||||||
40
assets/templates/default.html
Normal file
40
assets/templates/default.html
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="googlebot" content="noindex" />
|
||||||
|
<title>$title$</title>
|
||||||
|
<link rel="stylesheet" href="/css/fonts.css" />
|
||||||
|
<link rel="stylesheet" href="/css/default.css" />
|
||||||
|
<link rel="stylesheet" href="/css/pygentize.css" />
|
||||||
|
<link rel="stylesheet" href="/css/chao-theorems.css" />
|
||||||
|
<link rel="stylesheet" href="/css/sidenotes.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="toc">
|
||||||
|
<div id="contents-big">
|
||||||
|
<a href="#">
|
||||||
|
<p class="mini-header">Contents</p>
|
||||||
|
</a>
|
||||||
|
$toc$
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-space">
|
||||||
|
<header class="no-print">
|
||||||
|
<nav>
|
||||||
|
<a href="/">Home</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<main role="main">
|
||||||
|
<h1 class="pagetitle">$title$</h1>
|
||||||
|
$body$
|
||||||
|
</main>
|
||||||
|
<footer></footer>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
5
assets/templates/post-list.html
Normal file
5
assets/templates/post-list.html
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<ul class="post-list">
|
||||||
|
$for(posts)$
|
||||||
|
<li><a href="$url$">$title$</a></li>
|
||||||
|
$endfor$
|
||||||
|
</ul>
|
||||||
5
assets/templates/post.html
Normal file
5
assets/templates/post.html
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<article>
|
||||||
|
<section class="body">
|
||||||
|
$body$
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
37
hakyll-coflat.cabal
Normal file
37
hakyll-coflat.cabal
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
name: hakyll-coflat
|
||||||
|
version: 0.1.0.0
|
||||||
|
build-type: Simple
|
||||||
|
cabal-version: >= 1.10
|
||||||
|
|
||||||
|
|
||||||
|
executable site
|
||||||
|
hs-source-dirs: src
|
||||||
|
main-is: site.hs
|
||||||
|
other-modules: ChaoDoc, SideNoteHTML, Pangu
|
||||||
|
build-depends: base >= 4.18
|
||||||
|
, hakyll >= 4.15
|
||||||
|
, mtl >= 2.2.2
|
||||||
|
, pandoc
|
||||||
|
, pandoc-types >= 1.22.2.1
|
||||||
|
, pandoc-sidenote
|
||||||
|
, tagsoup
|
||||||
|
, text
|
||||||
|
, containers
|
||||||
|
-- , process
|
||||||
|
-- , regex-compat
|
||||||
|
, array
|
||||||
|
, filepath
|
||||||
|
-- , ghc-syntax-highlighter
|
||||||
|
-- , blaze-html >= 0.9
|
||||||
|
, megaparsec
|
||||||
|
, replace-megaparsec
|
||||||
|
ghc-options: -Weverything
|
||||||
|
-Wno-implicit-prelude
|
||||||
|
-Wno-missing-import-lists
|
||||||
|
-Wno-unused-packages
|
||||||
|
-Wno-missing-safe-haskell-mode
|
||||||
|
-Wno-all-missed-specialisations
|
||||||
|
-Wno-unsafe
|
||||||
|
-Wno-prepositive-qualified-module
|
||||||
|
-O2 -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
default-language: Haskell2010
|
||||||
25
makefile
Normal file
25
makefile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
COMMANDS := build watch rebuild clean
|
||||||
|
.PHONY: $(COMMANDS), publish
|
||||||
|
|
||||||
|
# Set the default goal, so running 'make' without arguments will run 'make build'.
|
||||||
|
.DEFAULT_GOAL := build
|
||||||
|
|
||||||
|
# ---
|
||||||
|
$(COMMANDS): site
|
||||||
|
@echo "Running command: ./site $@"
|
||||||
|
-@./site $@
|
||||||
|
|
||||||
|
|
||||||
|
# --- Rules ---
|
||||||
|
# using relative symlinks should be fine since everything only works at ./
|
||||||
|
|
||||||
|
|
||||||
|
site: src/site.hs src/ChaoDoc.hs
|
||||||
|
cabal build
|
||||||
|
ln -sf "$(shell cabal list-bin exe:site)" site
|
||||||
|
|
||||||
|
# move from katex to mathjax
|
||||||
|
# katex_cli:
|
||||||
|
# cd katex_rust_fork && cargo build --release
|
||||||
|
# ln -sf ./katex_rust_fork/target/release/katex_cli katex_cli
|
||||||
380
src/ChaoDoc.hs
Normal file
380
src/ChaoDoc.hs
Normal file
@@ -0,0 +1,380 @@
|
|||||||
|
{-# LANGUAGE BlockArguments #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
|
module ChaoDoc (chaoDocRead, chaoDocWrite, chaoDocPandocCompiler, chaoDocCompiler) where
|
||||||
|
|
||||||
|
import Control.Monad (guard)
|
||||||
|
import Control.Monad.State
|
||||||
|
import Data.Char (isSpace)
|
||||||
|
import Data.Either
|
||||||
|
import Data.Functor
|
||||||
|
import Data.List (find)
|
||||||
|
import qualified Data.Map as M
|
||||||
|
import Data.Maybe
|
||||||
|
import Data.Text (Text, pack)
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import Hakyll
|
||||||
|
import Pangu (isCJK, pangu)
|
||||||
|
import SideNoteHTML (usingSideNotesHTML)
|
||||||
|
import System.IO.Unsafe
|
||||||
|
import Text.Pandoc
|
||||||
|
-- import Text.Pandoc.Builder
|
||||||
|
import Text.Pandoc.Walk (query, walk, walkM)
|
||||||
|
|
||||||
|
cslFile :: String
|
||||||
|
cslFile = "assets/bib_style.csl"
|
||||||
|
|
||||||
|
bibFile :: String
|
||||||
|
bibFile = "ref.bib"
|
||||||
|
|
||||||
|
macroFile :: String
|
||||||
|
macroFile = "assets/math-macros.tex"
|
||||||
|
|
||||||
|
-- On mac, please do `export LANG=C` before using this thing
|
||||||
|
chaoDocRead :: ReaderOptions
|
||||||
|
chaoDocRead =
|
||||||
|
def
|
||||||
|
{ readerExtensions =
|
||||||
|
enableExtension Ext_tex_math_double_backslash $
|
||||||
|
enableExtension Ext_tex_math_single_backslash $
|
||||||
|
enableExtension Ext_latex_macros $
|
||||||
|
enableExtension Ext_raw_tex pandocExtensions
|
||||||
|
}
|
||||||
|
|
||||||
|
chaoDocWrite :: WriterOptions
|
||||||
|
chaoDocWrite =
|
||||||
|
def
|
||||||
|
{ writerHTMLMathMethod = MathML,
|
||||||
|
-- writerHtml5 = True,
|
||||||
|
-- writerHighlightStyle = Just syntaxHighlightingStyle,
|
||||||
|
writerNumberSections = True,
|
||||||
|
writerTableOfContents = True,
|
||||||
|
writerTOCDepth = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
chaoDocPandocCompiler :: Compiler (Item Pandoc)
|
||||||
|
chaoDocPandocCompiler = do
|
||||||
|
macros <- T.pack <$> loadBody (fromFilePath macroFile)
|
||||||
|
csl <- load $ fromFilePath cslFile
|
||||||
|
bib <- load $ fromFilePath bibFile
|
||||||
|
body <- getResourceBody
|
||||||
|
let bodyWithMacros =
|
||||||
|
fmap (T.unpack . prependMacros macros . normalizeTheoremFenceTitles . T.pack) body
|
||||||
|
prepare =
|
||||||
|
addMeta "link-citations" (MetaBool True)
|
||||||
|
. addMeta "reference-section-title" (MetaInlines [Str "References"])
|
||||||
|
. myFilter
|
||||||
|
readPandocWith chaoDocRead bodyWithMacros
|
||||||
|
>>= processPandocBiblio csl bib . fmap prepare
|
||||||
|
|
||||||
|
chaoDocCompiler :: Compiler (Item String)
|
||||||
|
chaoDocCompiler = chaoDocPandocCompiler <&> writePandocWith chaoDocWrite
|
||||||
|
|
||||||
|
addMeta :: T.Text -> MetaValue -> Pandoc -> Pandoc
|
||||||
|
addMeta name value (Pandoc meta a) =
|
||||||
|
let prevMap = unMeta meta
|
||||||
|
newMap = M.insert name value prevMap
|
||||||
|
newMeta = Meta newMap
|
||||||
|
in Pandoc newMeta a
|
||||||
|
|
||||||
|
myFilter :: Pandoc -> Pandoc
|
||||||
|
myFilter = usingSideNotesHTML chaoDocWrite . theoremFilter . panguFilter . equationFilter
|
||||||
|
|
||||||
|
pandocToInline :: Pandoc -> [Inline]
|
||||||
|
pandocToInline (Pandoc _ blocks) = go (reverse blocks)
|
||||||
|
where
|
||||||
|
go (Plain inlines : _) = inlines
|
||||||
|
go (Para inlines : _) = inlines
|
||||||
|
go (_ : xs) = go xs
|
||||||
|
go [] = []
|
||||||
|
|
||||||
|
incrementalBlock :: [Text]
|
||||||
|
incrementalBlock =
|
||||||
|
[ "Theorem",
|
||||||
|
"Conjecture",
|
||||||
|
"Definition",
|
||||||
|
"Example",
|
||||||
|
"Lemma",
|
||||||
|
"Problem",
|
||||||
|
"Proposition",
|
||||||
|
"Corollary",
|
||||||
|
"Observation",
|
||||||
|
"Figure"
|
||||||
|
]
|
||||||
|
|
||||||
|
otherBlock :: [Text]
|
||||||
|
otherBlock = ["Proof", "Remark"]
|
||||||
|
|
||||||
|
theoremClasses :: [Text]
|
||||||
|
theoremClasses = incrementalBlock ++ otherBlock
|
||||||
|
|
||||||
|
normalizeBlockClass :: Text -> Text
|
||||||
|
normalizeBlockClass = T.toTitle
|
||||||
|
|
||||||
|
hasAnyClass :: [Text] -> Attr -> Bool
|
||||||
|
hasAnyClass wanted = any ((`elem` wanted) . normalizeBlockClass) . getClass
|
||||||
|
|
||||||
|
matchedTheoremClass :: Attr -> Maybe Text
|
||||||
|
matchedTheoremClass = find (`elem` theoremClasses) . map normalizeBlockClass . getClass
|
||||||
|
|
||||||
|
normalizeTheoremFenceTitles :: Text -> Text
|
||||||
|
normalizeTheoremFenceTitles = T.unlines . map normalizeTheoremFenceTitle . T.lines
|
||||||
|
|
||||||
|
normalizeTheoremFenceTitle :: Text -> Text
|
||||||
|
normalizeTheoremFenceTitle line =
|
||||||
|
fromMaybe line do
|
||||||
|
let (indent, rest) = T.span isSpace line
|
||||||
|
(fence, afterFence) = T.span (== ':') rest
|
||||||
|
trimmed = T.stripStart afterFence
|
||||||
|
guard (T.length fence >= 3)
|
||||||
|
guard ("{" `T.isPrefixOf` trimmed)
|
||||||
|
let attrBody = T.drop 1 trimmed
|
||||||
|
(insideAttr, afterAttr) = T.breakOn "}" attrBody
|
||||||
|
guard (not $ T.null afterAttr)
|
||||||
|
let attrs = insideAttr
|
||||||
|
title = T.strip $ T.drop 1 afterAttr
|
||||||
|
guard (not $ T.null title)
|
||||||
|
guard (isTheoremAttr attrs)
|
||||||
|
let titleAttr = " title=\"" <> escapeAttrValue title <> "\""
|
||||||
|
pure $ indent <> fence <> " {" <> attrs <> titleAttr <> "}"
|
||||||
|
|
||||||
|
isTheoremAttr :: Text -> Bool
|
||||||
|
isTheoremAttr attrs =
|
||||||
|
any (`elem` theoremClasses) classes
|
||||||
|
where
|
||||||
|
classes =
|
||||||
|
map (normalizeBlockClass . T.drop 1) $
|
||||||
|
filter ("." `T.isPrefixOf`) $
|
||||||
|
T.words attrs
|
||||||
|
|
||||||
|
escapeAttrValue :: Text -> Text
|
||||||
|
escapeAttrValue =
|
||||||
|
T.concatMap \c -> case c of
|
||||||
|
'"' -> "\\\""
|
||||||
|
'\\' -> "\\\\"
|
||||||
|
_ -> T.singleton c
|
||||||
|
|
||||||
|
-- create a filter for theorems
|
||||||
|
getClass :: Attr -> [Text]
|
||||||
|
getClass (_, c, _) = c
|
||||||
|
|
||||||
|
addClass :: Attr -> Text -> Attr
|
||||||
|
addClass (a, b, c) d = (a, d : b, c)
|
||||||
|
|
||||||
|
addAttr :: Attr -> Text -> Text -> Attr
|
||||||
|
addAttr (a, b, c) x y = (a, b, (x, y) : c)
|
||||||
|
|
||||||
|
-- For each theorem, add a number, and also add add class theorem
|
||||||
|
preprocessTheorems :: Block -> State Int Block
|
||||||
|
preprocessTheorems (Div attr xs)
|
||||||
|
| isIncremental = do
|
||||||
|
curId <- get
|
||||||
|
put (curId + 1)
|
||||||
|
return $ Div (addAttr attr' "index" (pack $ show curId)) xs
|
||||||
|
| isOtherBlock = return $ Div attr' xs
|
||||||
|
| otherwise = return (Div attr xs)
|
||||||
|
where
|
||||||
|
isIncremental = hasAnyClass incrementalBlock attr
|
||||||
|
isOtherBlock = hasAnyClass otherBlock attr
|
||||||
|
theoremType = fromJust $ matchedTheoremClass attr
|
||||||
|
attr' = addAttr (normalizeTheoremClass attr theoremType) "type" theoremType
|
||||||
|
preprocessTheorems x = return x
|
||||||
|
|
||||||
|
normalizeTheoremClass :: Attr -> Text -> Attr
|
||||||
|
normalizeTheoremClass (ident, classes, attrs) theoremType =
|
||||||
|
(ident, theoremType : filter ((`notElem` theoremClasses) . normalizeBlockClass) classes, attrs)
|
||||||
|
|
||||||
|
theoremFilter :: Pandoc -> Pandoc
|
||||||
|
theoremFilter doc = walk makeTheorem $ autorefFilter $ evalState (walkM preprocessTheorems doc) 1
|
||||||
|
|
||||||
|
-- [index, type, idx]
|
||||||
|
theoremIndex :: Block -> [(Text, (Text, Text))]
|
||||||
|
theoremIndex (Div attr _)
|
||||||
|
| isNothing t = []
|
||||||
|
| isIncremental = [(idx, (fromJust t, fromJust index))]
|
||||||
|
| otherwise = []
|
||||||
|
where
|
||||||
|
(idx, _, parm) = attr
|
||||||
|
t = lookup "type" parm
|
||||||
|
index = lookup "index" parm
|
||||||
|
isIncremental = fromJust t `elem` incrementalBlock
|
||||||
|
theoremIndex _ = []
|
||||||
|
|
||||||
|
autoref :: [(Text, (Text, Text))] -> Inline -> Inline
|
||||||
|
autoref x (Cite citations inlines)
|
||||||
|
| valid = Link nullAttr [Str linkTitle] ("#" <> citeid, linkTitle)
|
||||||
|
| otherwise = Cite citations inlines
|
||||||
|
where
|
||||||
|
citeid = citationId $ head citations
|
||||||
|
valid = citeid `elem` map fst x
|
||||||
|
(theoremType, num) = fromJust $ lookup citeid x
|
||||||
|
linkTitle = theoremType <> " " <> num
|
||||||
|
autoref _ y = y
|
||||||
|
|
||||||
|
autorefFilter :: Pandoc -> Pandoc
|
||||||
|
autorefFilter x = walk (autoref links) x
|
||||||
|
where
|
||||||
|
links = query theoremIndex x
|
||||||
|
|
||||||
|
equationFilter :: Pandoc -> Pandoc
|
||||||
|
equationFilter doc = walk (equationAutoref links) processed
|
||||||
|
where
|
||||||
|
processed = evalState (walkM preprocessEquationBlock doc) 1
|
||||||
|
links = query equationIndex processed
|
||||||
|
|
||||||
|
preprocessEquationBlock :: Block -> State Int Block
|
||||||
|
preprocessEquationBlock (Para inlines) = Para <$> preprocessEquationInlines inlines
|
||||||
|
preprocessEquationBlock (Plain inlines) = Plain <$> preprocessEquationInlines inlines
|
||||||
|
preprocessEquationBlock x = return x
|
||||||
|
|
||||||
|
preprocessEquationInlines :: [Inline] -> State Int [Inline]
|
||||||
|
preprocessEquationInlines [] = return []
|
||||||
|
preprocessEquationInlines (Math DisplayMath math : Space : Str s : xs)
|
||||||
|
| Just eqId <- parseEquationLabel s = do
|
||||||
|
curId <- get
|
||||||
|
put (curId + 1)
|
||||||
|
(makeEquation eqId curId math :) <$> preprocessEquationInlines xs
|
||||||
|
preprocessEquationInlines (Math DisplayMath math : Str s : xs)
|
||||||
|
| Just eqId <- parseEquationLabel s = do
|
||||||
|
curId <- get
|
||||||
|
put (curId + 1)
|
||||||
|
(makeEquation eqId curId math :) <$> preprocessEquationInlines xs
|
||||||
|
preprocessEquationInlines (Math DisplayMath math : xs) =
|
||||||
|
(wrapDisplayMath math :) <$> preprocessEquationInlines xs
|
||||||
|
preprocessEquationInlines (x : xs) =
|
||||||
|
(x :) <$> preprocessEquationInlines xs
|
||||||
|
|
||||||
|
parseEquationLabel :: Text -> Maybe Text
|
||||||
|
parseEquationLabel s = do
|
||||||
|
label <- T.stripPrefix "{#" s >>= T.stripSuffix "}"
|
||||||
|
guard ("eq:" `T.isPrefixOf` label)
|
||||||
|
pure label
|
||||||
|
|
||||||
|
wrapDisplayMath :: Text -> Inline
|
||||||
|
wrapDisplayMath math =
|
||||||
|
Span ("", ["math-container"], []) [Math DisplayMath math]
|
||||||
|
|
||||||
|
makeEquation :: Text -> Int -> Text -> Inline
|
||||||
|
makeEquation eqId idx math =
|
||||||
|
Span
|
||||||
|
(eqId, ["equation"], [("index", pack $ show idx)])
|
||||||
|
[ wrapDisplayMath math,
|
||||||
|
Span ("", ["equation-number"], []) [Str $ "(" <> pack (show idx) <> ")"]
|
||||||
|
]
|
||||||
|
|
||||||
|
equationIndex :: Inline -> [(Text, Text)]
|
||||||
|
equationIndex (Span (eqId, classes, attrs) _)
|
||||||
|
| "equation" `elem` classes
|
||||||
|
, not (T.null eqId)
|
||||||
|
, Just idx <- lookup "index" attrs =
|
||||||
|
[(eqId, idx)]
|
||||||
|
equationIndex _ = []
|
||||||
|
|
||||||
|
equationAutoref :: [(Text, Text)] -> Inline -> Inline
|
||||||
|
equationAutoref x (Cite citations inlines)
|
||||||
|
| valid = Link nullAttr [Str linkTitle] ("#" <> citeid, linkTitle)
|
||||||
|
| otherwise = Cite citations inlines
|
||||||
|
where
|
||||||
|
citeid = citationId $ head citations
|
||||||
|
valid = citeid `elem` map fst x
|
||||||
|
num = fromJust $ lookup citeid x
|
||||||
|
linkTitle = "Eq. (" <> num <> ")"
|
||||||
|
equationAutoref _ y = y
|
||||||
|
|
||||||
|
-- processCitations works on AST. If you want to use citations in theorem name,
|
||||||
|
-- then you need to convert citations there to AST as well and then use processCitations\
|
||||||
|
-- Thus one need to apply the theorem filter first.
|
||||||
|
-- autoref still does not work.
|
||||||
|
mathMacros :: Text
|
||||||
|
mathMacros = unsafePerformIO (pack <$> readFile macroFile)
|
||||||
|
{-# NOINLINE mathMacros #-}
|
||||||
|
|
||||||
|
prependMacros :: Text -> Text -> Text
|
||||||
|
prependMacros macros body = macros <> "\n\n" <> body
|
||||||
|
|
||||||
|
prependMathMacros :: Text -> Text
|
||||||
|
prependMathMacros = prependMacros mathMacros
|
||||||
|
|
||||||
|
thmNamePandoc :: Text -> Pandoc
|
||||||
|
thmNamePandoc x =
|
||||||
|
fromRight (Pandoc nullMeta []) . runPure $
|
||||||
|
readMarkdown chaoDocRead (prependMathMacros x)
|
||||||
|
|
||||||
|
makeTheorem :: Block -> Block
|
||||||
|
makeTheorem (Div attr xs)
|
||||||
|
| isNothing t = Div attr xs
|
||||||
|
| otherwise = Div (addClass attr "theorem-environment") (Plain [header] : xs)
|
||||||
|
where
|
||||||
|
(_, _, parm) = attr
|
||||||
|
t = lookup "type" parm
|
||||||
|
name = lookup "title" parm
|
||||||
|
index = lookup "index" parm
|
||||||
|
header = Span (addClass nullAttr "theorem-header") [typetext, indextext, nametext]
|
||||||
|
typetext = Span (addClass nullAttr "type") [Str $ fromJust t]
|
||||||
|
indextext =
|
||||||
|
if isNothing index
|
||||||
|
then Str ""
|
||||||
|
else Span (addClass nullAttr "index") [Str $ fromJust index]
|
||||||
|
nametext =
|
||||||
|
if isNothing name
|
||||||
|
then Str ""
|
||||||
|
else Span (addClass nullAttr "name") (pandocToInline $ thmNamePandoc $ fromJust name)
|
||||||
|
makeTheorem x = x
|
||||||
|
|
||||||
|
-- pangu filter
|
||||||
|
lastChar :: Inline -> Maybe Char
|
||||||
|
lastChar e = case e of
|
||||||
|
Str s -> if null (T.unpack s) then Nothing else Just (last (T.unpack s))
|
||||||
|
Emph is -> lastCharList is
|
||||||
|
Strong is -> lastCharList is
|
||||||
|
Strikeout is -> lastCharList is
|
||||||
|
Link _ is _ -> lastCharList is
|
||||||
|
Span _ is -> lastCharList is
|
||||||
|
Quoted _ is -> lastCharList is
|
||||||
|
_ -> Nothing
|
||||||
|
where
|
||||||
|
lastCharList [] = Nothing
|
||||||
|
lastCharList is = lastChar (last is)
|
||||||
|
|
||||||
|
firstChar :: Inline -> Maybe Char
|
||||||
|
firstChar e = case e of
|
||||||
|
Str s -> if null (T.unpack s) then Nothing else Just (head (T.unpack s))
|
||||||
|
Emph is -> firstCharList is
|
||||||
|
Strong is -> firstCharList is
|
||||||
|
Strikeout is -> firstCharList is
|
||||||
|
Link _ is _ -> firstCharList is
|
||||||
|
Span _ is -> firstCharList is
|
||||||
|
Quoted _ is -> firstCharList is
|
||||||
|
_ -> Nothing
|
||||||
|
where
|
||||||
|
firstCharList [] = Nothing
|
||||||
|
firstCharList is = firstChar (head is)
|
||||||
|
|
||||||
|
panguInline :: Inline -> Inline
|
||||||
|
panguInline e = case e of
|
||||||
|
Str s -> Str (pangu s)
|
||||||
|
Emph is -> Emph (panguInlines is)
|
||||||
|
Strong is -> Strong (panguInlines is)
|
||||||
|
Strikeout is -> Strikeout (panguInlines is)
|
||||||
|
Link at is tg -> Link at (panguInlines is) tg
|
||||||
|
Span at is -> Span at (panguInlines is)
|
||||||
|
Quoted qt is -> Quoted qt (panguInlines is)
|
||||||
|
_ -> e
|
||||||
|
|
||||||
|
panguInlines :: [Inline] -> [Inline]
|
||||||
|
panguInlines = foldr (addSpace . panguInline) []
|
||||||
|
where
|
||||||
|
addSpace x [] = [x]
|
||||||
|
addSpace x (y : ys)
|
||||||
|
| shouldSpace x y = x : Space : y : ys
|
||||||
|
| otherwise = x : y : ys
|
||||||
|
shouldSpace x y = case (lastChar x, firstChar y) of
|
||||||
|
(Just lc, Just fc) -> isCJK lc /= isCJK fc
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
panguFilter :: Pandoc -> Pandoc
|
||||||
|
panguFilter = walk transformBlocks
|
||||||
|
where
|
||||||
|
transformBlocks :: Block -> Block
|
||||||
|
transformBlocks (Para inlines) = Para (panguInlines inlines)
|
||||||
|
transformBlocks x = x
|
||||||
227
src/Pangu.hs
Normal file
227
src/Pangu.hs
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
|
module Pangu (pangu, isCJK) where
|
||||||
|
|
||||||
|
import Data.Function (fix)
|
||||||
|
import Data.Text (Text)
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import Data.Void (Void)
|
||||||
|
import Replace.Megaparsec (streamEdit)
|
||||||
|
import Text.Megaparsec
|
||||||
|
import Text.Megaparsec.Char
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
type Parser = Parsec Void Text
|
||||||
|
|
||||||
|
type Rule = Parser Text
|
||||||
|
|
||||||
|
type RuleSet = [Rule]
|
||||||
|
|
||||||
|
applyUntilFixed :: Rule -> Text -> Text
|
||||||
|
applyUntilFixed rule =
|
||||||
|
fix
|
||||||
|
( \loop current ->
|
||||||
|
let next = streamEdit (try rule) id current
|
||||||
|
in if next == current then next else loop next
|
||||||
|
)
|
||||||
|
|
||||||
|
applyRulesRecursively :: RuleSet -> Text -> Text
|
||||||
|
applyRulesRecursively rules input = foldl (flip applyUntilFixed) input rules
|
||||||
|
|
||||||
|
applyRules :: RuleSet -> Text -> Text
|
||||||
|
applyRules rules input = foldl (flip applyOnce) input rules
|
||||||
|
where
|
||||||
|
applyOnce rule = streamEdit (try rule) id
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- rules for pangu
|
||||||
|
|
||||||
|
-- alphaNumChar from megaparsec matches CJK chars...
|
||||||
|
-- need to implement a new one
|
||||||
|
alphanumericChar :: Parser Char
|
||||||
|
alphanumericChar = satisfy $ \c ->
|
||||||
|
(c >= 'a' && c <= 'z')
|
||||||
|
|| (c >= 'A' && c <= 'Z')
|
||||||
|
|| (c >= '0' && c <= '9')
|
||||||
|
|
||||||
|
-- | Check if a character falls within the CJK ranges provided
|
||||||
|
isCJK :: Char -> Bool
|
||||||
|
isCJK c = any (\(start, end) -> c >= start && c <= end) cjkRanges
|
||||||
|
where
|
||||||
|
cjkRanges =
|
||||||
|
[ ('\x2e80', '\x2eff'),
|
||||||
|
('\x2f00', '\x2fdf'),
|
||||||
|
('\x3040', '\x309f'),
|
||||||
|
('\x30a0', '\x30fa'),
|
||||||
|
('\x30fc', '\x30ff'),
|
||||||
|
('\x3100', '\x312f'),
|
||||||
|
('\x3200', '\x32ff'),
|
||||||
|
('\x3400', '\x4dbf'),
|
||||||
|
('\x4e00', '\x9fff'),
|
||||||
|
('\xf900', '\xfaff')
|
||||||
|
]
|
||||||
|
|
||||||
|
convertToFullwidth :: Char -> Char
|
||||||
|
convertToFullwidth c =
|
||||||
|
case c of
|
||||||
|
':' -> ':'
|
||||||
|
'.' -> '。'
|
||||||
|
'~' -> '~'
|
||||||
|
'!' -> '!'
|
||||||
|
'?' -> '?'
|
||||||
|
',' -> ','
|
||||||
|
';' -> ';'
|
||||||
|
'\"' -> '”'
|
||||||
|
'\'' -> '’'
|
||||||
|
_ -> c
|
||||||
|
|
||||||
|
-- A parser that matches a single CJK character
|
||||||
|
cjkChar :: Parser Char
|
||||||
|
cjkChar = satisfy isCJK
|
||||||
|
|
||||||
|
-- use python.py as reference for these rules
|
||||||
|
|
||||||
|
fullwidthCJKsymCJK :: Rule
|
||||||
|
fullwidthCJKsymCJK = do
|
||||||
|
lcjk <- cjkChar
|
||||||
|
_ <- many (char ' ')
|
||||||
|
sym <- try (some (char ':')) <|> count 1 (char '.')
|
||||||
|
_ <- many (char ' ')
|
||||||
|
rcjk <- cjkChar
|
||||||
|
let transformedsym = map convertToFullwidth sym
|
||||||
|
return $ T.pack $ [lcjk] ++ transformedsym ++ [rcjk]
|
||||||
|
|
||||||
|
fullwidthCJKsym :: Rule
|
||||||
|
fullwidthCJKsym = do
|
||||||
|
cjk <- cjkChar
|
||||||
|
_ <- many (char ' ')
|
||||||
|
sym <- some $ oneOf ("~!?,;" :: [Char])
|
||||||
|
_ <- many (char ' ')
|
||||||
|
let transformedsym = T.pack $ map convertToFullwidth sym
|
||||||
|
return $ T.pack [cjk] <> transformedsym
|
||||||
|
|
||||||
|
dotsCJK :: Rule
|
||||||
|
dotsCJK = do
|
||||||
|
dots <- chunk "..." <|> chunk "…"
|
||||||
|
cjk <- cjkChar
|
||||||
|
return $ dots <> T.pack (" " ++ [cjk])
|
||||||
|
|
||||||
|
fixCJKcolAN :: Rule
|
||||||
|
fixCJKcolAN = do
|
||||||
|
cjk <- cjkChar
|
||||||
|
_ <- char ':'
|
||||||
|
an <- alphanumericChar
|
||||||
|
return $ T.pack $ [cjk] ++ ":" ++ [an]
|
||||||
|
|
||||||
|
-- quotes
|
||||||
|
-- seems confusing ...
|
||||||
|
quotesym :: [Char]
|
||||||
|
quotesym = "'`\x05f4\""
|
||||||
|
|
||||||
|
cjkquote :: Rule
|
||||||
|
cjkquote = do
|
||||||
|
cjk <- cjkChar
|
||||||
|
quote <- oneOf quotesym
|
||||||
|
return $ T.pack $ [cjk] ++ " " ++ [quote]
|
||||||
|
|
||||||
|
quoteCJK :: Rule
|
||||||
|
quoteCJK = do
|
||||||
|
quote <- oneOf quotesym
|
||||||
|
cjk <- cjkChar
|
||||||
|
return $ T.pack $ [quote] ++ " " ++ [cjk]
|
||||||
|
|
||||||
|
fixQuote :: Rule
|
||||||
|
fixQuote = do
|
||||||
|
openQuotes <- T.pack <$> some (oneOf quotesym)
|
||||||
|
_ <- many spaceChar
|
||||||
|
content <- T.pack <$> someTill anySingle (lookAhead $ some (oneOf quotesym))
|
||||||
|
closeQuotes <- T.pack <$> some (oneOf quotesym)
|
||||||
|
return $ openQuotes <> T.strip content <> closeQuotes
|
||||||
|
|
||||||
|
cjkpossessivequote :: Rule
|
||||||
|
cjkpossessivequote = do
|
||||||
|
cjk <- cjkChar
|
||||||
|
_ <- char '\''
|
||||||
|
_ <- lookAhead $ anySingleBut 's'
|
||||||
|
return $ T.pack $ cjk : " '"
|
||||||
|
|
||||||
|
-- This singlequoteCJK rule will turn '你好' into ' 你好'
|
||||||
|
-- which seems not desirable...
|
||||||
|
-- however, the behavior is aligned with python version
|
||||||
|
singlequoteCJK :: Rule
|
||||||
|
singlequoteCJK = do
|
||||||
|
_ <- char '\''
|
||||||
|
cjk <- cjkChar
|
||||||
|
return $ T.pack $ "' " ++ [cjk]
|
||||||
|
|
||||||
|
fixPossessivequote :: Rule
|
||||||
|
fixPossessivequote = do
|
||||||
|
pre <- cjkChar <|> alphanumericChar
|
||||||
|
_ <- some spaceChar
|
||||||
|
_ <- chunk "'s"
|
||||||
|
return $ T.pack $ pre : "'s"
|
||||||
|
|
||||||
|
-- hash
|
||||||
|
hashANSCJKhash :: Rule
|
||||||
|
hashANSCJKhash = do
|
||||||
|
cjk1 <- cjkChar
|
||||||
|
_ <- char '#'
|
||||||
|
mid <- some cjkChar
|
||||||
|
_ <- char '#'
|
||||||
|
cjk2 <- cjkChar
|
||||||
|
return $ T.pack $ [cjk1] ++ " #" ++ mid ++ "# " ++ [cjk2]
|
||||||
|
|
||||||
|
cjkhash :: Rule
|
||||||
|
cjkhash = do
|
||||||
|
cjk <- cjkChar
|
||||||
|
_ <- char '#'
|
||||||
|
_ <- lookAhead $ anySingleBut ' '
|
||||||
|
return $ T.pack $ cjk : " #"
|
||||||
|
|
||||||
|
hashcjk :: Rule
|
||||||
|
hashcjk = do
|
||||||
|
_ <- char '#'
|
||||||
|
_ <- lookAhead $ anySingleBut ' '
|
||||||
|
cjk <- cjkChar
|
||||||
|
return $ T.pack $ "# " ++ [cjk]
|
||||||
|
|
||||||
|
-- operators
|
||||||
|
cjkOPTan :: Rule
|
||||||
|
cjkOPTan = do
|
||||||
|
cjk <- cjkChar
|
||||||
|
opt <- oneOf ("+-=*/&|<>%" :: [Char])
|
||||||
|
an <- alphanumericChar
|
||||||
|
return $ T.pack [cjk, ' ', opt, ' ', an]
|
||||||
|
|
||||||
|
anOPTcjk :: Rule
|
||||||
|
anOPTcjk = do
|
||||||
|
an <- alphanumericChar
|
||||||
|
opt <- oneOf ("+-=*/&|<>%" :: [Char])
|
||||||
|
cjk <- cjkChar
|
||||||
|
return $ T.pack [an, ' ', opt, ' ', cjk]
|
||||||
|
|
||||||
|
-- slash/bracket rules are not implemented
|
||||||
|
|
||||||
|
-- CJK and alphanumeric without space
|
||||||
|
|
||||||
|
cjkans :: Rule
|
||||||
|
cjkans = do
|
||||||
|
cjk <- cjkChar
|
||||||
|
_ <- lookAhead (alphanumericChar <|> oneOf ("@$%^&*-+\\=|/" :: [Char]))
|
||||||
|
return $ T.pack [cjk, ' ']
|
||||||
|
|
||||||
|
anscjk :: Rule
|
||||||
|
anscjk = do
|
||||||
|
an <- alphanumericChar <|> oneOf ("~!$%^&*-+\\=|;:,./?" :: [Char])
|
||||||
|
_ <- lookAhead cjkChar
|
||||||
|
return $ T.pack [an, ' ']
|
||||||
|
|
||||||
|
-- rule set, the order matters
|
||||||
|
recursiveRules :: RuleSet
|
||||||
|
recursiveRules = [fullwidthCJKsymCJK, fullwidthCJKsym]
|
||||||
|
|
||||||
|
onepassRules :: RuleSet
|
||||||
|
onepassRules = [anscjk, cjkans]
|
||||||
|
|
||||||
|
pangu :: Text -> Text
|
||||||
|
pangu input = applyRules onepassRules $ applyRulesRecursively recursiveRules input
|
||||||
161
src/SideNoteHTML.hs
Normal file
161
src/SideNoteHTML.hs
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
{-# LANGUAGE BangPatterns #-}
|
||||||
|
{-# LANGUAGE DerivingStrategies #-}
|
||||||
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
{- |
|
||||||
|
Module : Text.Pandoc.SideNoteHTML
|
||||||
|
Description : Convert pandoc footnotes to sidenotes
|
||||||
|
Copyright : (c) Tony Zorman 2023
|
||||||
|
License : MIT
|
||||||
|
Maintainer : Tony Zorman <soliditsallgood@mailbox.org>
|
||||||
|
Stability : experimental
|
||||||
|
Portability : non-portable
|
||||||
|
-}
|
||||||
|
module SideNoteHTML (usingSideNotesHTML) where
|
||||||
|
|
||||||
|
import Control.Monad (foldM)
|
||||||
|
import Control.Monad.State (State, get, modify', runState)
|
||||||
|
import Data.Text (Text)
|
||||||
|
import Text.Pandoc (runPure, writeHtml5String)
|
||||||
|
import Text.Pandoc.Definition (Block (..), Inline (..), Pandoc (..))
|
||||||
|
import Text.Pandoc.Options (WriterOptions)
|
||||||
|
import Text.Pandoc.Shared (tshow)
|
||||||
|
import Text.Pandoc.Walk (walkM)
|
||||||
|
import qualified Data.Text as T
|
||||||
|
|
||||||
|
-- type NoteType :: Type
|
||||||
|
data NoteType = Sidenote | Marginnote
|
||||||
|
deriving stock (Show, Eq)
|
||||||
|
|
||||||
|
-- type SidenoteState :: Type
|
||||||
|
data SidenoteState = SNS
|
||||||
|
{ _writer :: !WriterOptions
|
||||||
|
, counter :: !Int
|
||||||
|
}
|
||||||
|
|
||||||
|
-- type Sidenote :: Type -> Type
|
||||||
|
type Sidenote = State SidenoteState
|
||||||
|
|
||||||
|
-- | Like 'Text.Pandoc.SideNote.usingSideNotes', but immediately
|
||||||
|
-- pre-render the sidenotes. This has the advantage that sidenotes may
|
||||||
|
-- be wrapped in a @<div>@ (instead of a 'Span'), which allows arbitrary
|
||||||
|
-- blocks to be nested in them. The disadvantage is that one now has to
|
||||||
|
-- specify the 'WriterOptions' for the current document, meaning this is
|
||||||
|
-- meant to be used as a module and is unlikely to be useful as a
|
||||||
|
-- standalone application.
|
||||||
|
--
|
||||||
|
-- ==== __Example__
|
||||||
|
--
|
||||||
|
-- Using this function with <https://jaspervdj.be/hakyll/ hakyll> could
|
||||||
|
-- look something like the following, defining an equivalent to the
|
||||||
|
-- default @pandocCompiler@.
|
||||||
|
--
|
||||||
|
-- > myPandocCompiler :: Compiler (Item String)
|
||||||
|
-- > myPandocCompiler =
|
||||||
|
-- > pandocCompilerWithTransformM
|
||||||
|
-- > defaultHakyllReaderOptions
|
||||||
|
-- > defaultHakyllWriterOptions
|
||||||
|
-- > (usingSideNotesHTML defaultHakyllWriterOptions)
|
||||||
|
--
|
||||||
|
usingSideNotesHTML :: WriterOptions -> Pandoc -> Pandoc
|
||||||
|
usingSideNotesHTML writer (Pandoc meta blocks) =
|
||||||
|
-- Drop a superfluous paragraph at the start of the document.
|
||||||
|
Pandoc meta . someStart . walkBlocks (SNS writer 0) $ blocks
|
||||||
|
where
|
||||||
|
someStart :: [Block] -> [Block]
|
||||||
|
someStart = \case
|
||||||
|
(Para [Str ""] : bs) -> bs
|
||||||
|
bs -> bs
|
||||||
|
|
||||||
|
walkBlocks :: SidenoteState -> [Block] -> [Block]
|
||||||
|
walkBlocks sns = \case
|
||||||
|
[] -> []
|
||||||
|
(b : bs) -> b' <> walkBlocks s' bs
|
||||||
|
where (b', s') = walkM mkSidenote [b] `runState` sns
|
||||||
|
|
||||||
|
-- Sidenotes can probably appear in more places; this should be
|
||||||
|
-- filled-in at some point.
|
||||||
|
mkSidenote :: [Block] -> Sidenote [Block]
|
||||||
|
mkSidenote = foldM (\acc b -> (acc <>) <$> single b) []
|
||||||
|
where
|
||||||
|
-- Try to find and render a sidenote in a single block.
|
||||||
|
single :: Block -> Sidenote [Block]
|
||||||
|
single = \case
|
||||||
|
-- Simulate a paragraph by inserting a dummy block; this is needed
|
||||||
|
-- in case two consecutive paragraphs have sidenotes, or a paragraph
|
||||||
|
-- doesn't have one at all.
|
||||||
|
Para inlines -> (Para [Str ""] :) <$> renderSidenote [] inlines
|
||||||
|
Plain inlines -> renderSidenote [] inlines
|
||||||
|
OrderedList attrs bs -> (:[]) . OrderedList attrs <$> traverse mkSidenote bs
|
||||||
|
BulletList bs -> (:[]) . BulletList <$> traverse mkSidenote bs
|
||||||
|
block -> pure [block]
|
||||||
|
|
||||||
|
renderSidenote :: [Inline] -> [Inline] -> Sidenote [Block]
|
||||||
|
renderSidenote !inlines = \case
|
||||||
|
[] -> pure [plain inlines]
|
||||||
|
Note bs : xs -> do block <- go bs
|
||||||
|
mappend [ -- Start gluing before, see [Note Comment].
|
||||||
|
plain (RawInline "html" commentStart : inlines)
|
||||||
|
, block
|
||||||
|
]
|
||||||
|
<$> renderSidenote
|
||||||
|
[RawInline "html" commentEnd] -- End gluing after
|
||||||
|
xs
|
||||||
|
b : xs -> renderSidenote (b : inlines) xs
|
||||||
|
where
|
||||||
|
go :: [Block] -> Sidenote Block
|
||||||
|
go blocks = do
|
||||||
|
SNS w i <- get <* modify' (\sns -> sns{ counter = 1 + counter sns })
|
||||||
|
let (typ, noteText) = getNoteType (render w blocks)
|
||||||
|
pure . RawBlock "html" $
|
||||||
|
mconcat [ commentEnd -- End gluing before
|
||||||
|
, label typ i <> input i <> note typ noteText
|
||||||
|
, commentStart -- Start gluing after
|
||||||
|
]
|
||||||
|
|
||||||
|
-- The '{-}' symbol differentiates between margin note and side note.
|
||||||
|
getNoteType :: Text -> (NoteType, Text)
|
||||||
|
getNoteType t
|
||||||
|
| "{-} " `T.isPrefixOf` t = (Marginnote, T.drop 4 t)
|
||||||
|
| otherwise = (Sidenote , t)
|
||||||
|
|
||||||
|
render :: WriterOptions -> [Block] -> Text
|
||||||
|
render w bs = case runPure (writeHtml5String w (Pandoc mempty bs)) of
|
||||||
|
Left err -> error $ "Text.Pandoc.SideNoteHTML.writePandocWith: " ++ show err
|
||||||
|
Right txt -> T.drop 1 (T.dropWhile (/= '\n') txt)
|
||||||
|
|
||||||
|
commentEnd :: T.Text
|
||||||
|
commentEnd = "-->"
|
||||||
|
|
||||||
|
commentStart :: T.Text
|
||||||
|
commentStart = "<!--"
|
||||||
|
|
||||||
|
plain :: [Inline] -> Block
|
||||||
|
plain = Plain . reverse
|
||||||
|
|
||||||
|
label :: NoteType -> Int -> Text
|
||||||
|
label nt i = "<label for=\"sn-" <> tshow i <> "\" class=\"margin-toggle" <> sidenoteNumber <> "\">" <> altSymbol <> "</label>"
|
||||||
|
where
|
||||||
|
sidenoteNumber :: Text = case nt of
|
||||||
|
Sidenote -> " sidenote-number"
|
||||||
|
Marginnote -> ""
|
||||||
|
altSymbol :: Text = case nt of
|
||||||
|
Sidenote -> ""
|
||||||
|
Marginnote -> "⊕"
|
||||||
|
|
||||||
|
input :: Int -> Text
|
||||||
|
input i = "<input type=\"checkbox\" id=\"sn-" <> tshow i <> "\" class=\"margin-toggle\"/>"
|
||||||
|
|
||||||
|
note :: NoteType -> Text -> Text
|
||||||
|
note nt body = "<div class=\"" <> T.toLower (tshow nt) <> "\">" <> body <> "</div>"
|
||||||
|
|
||||||
|
{- [Note Comment]
|
||||||
|
|
||||||
|
This is obviously horrible, but we have to do this in order for the
|
||||||
|
blocks (which are now not inline elements anymore!) immediately before
|
||||||
|
and after the sidenote to be "glued" to the sidenote itself. In this
|
||||||
|
way, the number indicating the sidenote does not have an extra space
|
||||||
|
associated to it on either side, which otherwise would be the case.
|
||||||
|
|
||||||
|
-}
|
||||||
111
src/site.hs
Normal file
111
src/site.hs
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
{-# LANGUAGE BlockArguments #-}
|
||||||
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
|
||||||
|
import ChaoDoc
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import Hakyll
|
||||||
|
import System.FilePath
|
||||||
|
import Text.Pandoc
|
||||||
|
|
||||||
|
mds :: Pattern
|
||||||
|
mds = "main.md"
|
||||||
|
|
||||||
|
config :: Configuration
|
||||||
|
config =
|
||||||
|
defaultConfiguration
|
||||||
|
{ ignoreFile = \path ->
|
||||||
|
ignoreFile defaultConfiguration path
|
||||||
|
|| ".git" `elem` splitDirectories (normalise path)
|
||||||
|
}
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = hakyllWith config $ do
|
||||||
|
match "images/**" $ do
|
||||||
|
route idRoute
|
||||||
|
compile copyFileCompiler
|
||||||
|
|
||||||
|
match "assets/math-macros.tex" $ compile getResourceBody
|
||||||
|
|
||||||
|
match "assets/bib_style.csl" $ compile cslCompiler
|
||||||
|
|
||||||
|
match "ref.bib" $ compile biblioCompiler
|
||||||
|
|
||||||
|
match "assets/fonts/*" $ do
|
||||||
|
route $ gsubRoute "assets/fonts/" (const "fonts/")
|
||||||
|
compile copyFileCompiler
|
||||||
|
|
||||||
|
match "assets/favicon.ico" $ do
|
||||||
|
route $ constRoute "favicon.ico"
|
||||||
|
compile copyFileCompiler
|
||||||
|
|
||||||
|
match "assets/css/*" $ do
|
||||||
|
route $ gsubRoute "assets/css/" (const "css/")
|
||||||
|
compile compressCssCompiler
|
||||||
|
|
||||||
|
match mds $ do
|
||||||
|
route $ setExtension "html"
|
||||||
|
compile $ do
|
||||||
|
tocCtx <- getTocCtx defaultContext
|
||||||
|
chaoDocCompiler
|
||||||
|
>>= loadAndApplyTemplate "assets/templates/post.html" tocCtx
|
||||||
|
>>= loadAndApplyTemplate "assets/templates/default.html" tocCtx
|
||||||
|
>>= relativizeUrls
|
||||||
|
|
||||||
|
create ["index.html"] $ do
|
||||||
|
route idRoute
|
||||||
|
compile $ do
|
||||||
|
posts <- loadAll mds
|
||||||
|
let indexCtx =
|
||||||
|
constField "title" "Notes"
|
||||||
|
`mappend` constField "toc" ""
|
||||||
|
`mappend` listField "posts" postCtx (return posts)
|
||||||
|
`mappend` defaultContext
|
||||||
|
makeItem ""
|
||||||
|
>>= loadAndApplyTemplate "assets/templates/post-list.html" indexCtx
|
||||||
|
>>= loadAndApplyTemplate "assets/templates/default.html" indexCtx
|
||||||
|
>>= relativizeUrls
|
||||||
|
|
||||||
|
match "assets/templates/*" $ compile templateBodyCompiler
|
||||||
|
|
||||||
|
postCtx :: Context String
|
||||||
|
postCtx =
|
||||||
|
dateField "date" "%B %e, %Y"
|
||||||
|
<> dateField "date" "%Y-%m-%d"
|
||||||
|
<> defaultContext
|
||||||
|
|
||||||
|
-- toc from https://github.com/slotThe/slotThe.github.io
|
||||||
|
getTocCtx :: Context a -> Compiler (Context a)
|
||||||
|
getTocCtx ctx = do
|
||||||
|
noToc <- (Just "true" ==) <$> (getUnderlying >>= (`getMetadataField` "no-toc"))
|
||||||
|
writerOpts <- mkTocWriter defaultHakyllWriterOptions
|
||||||
|
toc <- writePandocWith writerOpts <$> chaoDocPandocCompiler
|
||||||
|
pure $
|
||||||
|
mconcat
|
||||||
|
[ ctx,
|
||||||
|
constField "toc" $ killLinkIds (itemBody toc),
|
||||||
|
if noToc then boolField "no-toc" (pure noToc) else mempty
|
||||||
|
]
|
||||||
|
where
|
||||||
|
mkTocWriter :: WriterOptions -> Compiler WriterOptions
|
||||||
|
mkTocWriter writerOpts = do
|
||||||
|
tmpl <- either (const Nothing) Just <$> unsafeCompiler (compileTemplate "" "$toc$")
|
||||||
|
pure $
|
||||||
|
writerOpts
|
||||||
|
{ writerTableOfContents = True,
|
||||||
|
writerTOCDepth = 2,
|
||||||
|
writerTemplate = tmpl,
|
||||||
|
writerHTMLMathMethod = MathML
|
||||||
|
}
|
||||||
|
|
||||||
|
asTxt :: (T.Text -> T.Text) -> String -> String
|
||||||
|
asTxt f = T.unpack . f . T.pack
|
||||||
|
|
||||||
|
killLinkIds :: String -> String
|
||||||
|
killLinkIds = asTxt (mconcat . go . T.splitOn "id=\"toc-")
|
||||||
|
where
|
||||||
|
go :: [T.Text] -> [T.Text]
|
||||||
|
go = \case
|
||||||
|
[] -> []
|
||||||
|
x : xs -> x : map (T.drop 1 . T.dropWhile (/= '\"')) xs
|
||||||
Reference in New Issue
Block a user