Compare commits
6 Commits
5e0c735ed3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 43492094bc | |||
| 0bed1d6976 | |||
| 63010da18d | |||
| a0affeb5c4 | |||
| e4689268f2 | |||
| f592483e69 |
@@ -1,62 +1,86 @@
|
|||||||
:root {
|
:root {
|
||||||
--color-text: black;
|
--color-text: black;
|
||||||
--color-tag1: gray;
|
--color-tag1: gray;
|
||||||
--color-tag2: darkolivegreen;
|
|
||||||
--color-bg: white;
|
--color-bg: white;
|
||||||
--color-notice: #fb4f4f;
|
--color-notice: #fb4f4f;
|
||||||
|
--color-link: #0645ad;
|
||||||
|
--color-link-visited: #551a8b;
|
||||||
|
--layout-max-width: 1350px;
|
||||||
|
--mobile-max-width: 876px;
|
||||||
|
--content-max-width: 800px;
|
||||||
|
--toc-width: 33%;
|
||||||
|
--toc-width-no-sidenotes: 18rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
scrollbar-gutter: stable;
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
font-size: 110%;
|
font-size: 110%;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
scrollbar-gutter: stable;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Lato', -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
font-family:
|
||||||
|
"Lato",
|
||||||
|
-apple-system,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
"PingFang SC",
|
||||||
|
"Microsoft YaHei",
|
||||||
|
sans-serif;
|
||||||
font-optical-sizing: auto;
|
font-optical-sizing: auto;
|
||||||
font-weight: 400;
|
|
||||||
font-style: normal;
|
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
line-height: 140%;
|
line-height: 1.4;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
background-color: var(--color-bg);
|
background-color: var(--color-bg);
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
body a {
|
a {
|
||||||
|
color: var(--color-link);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body a:hover {
|
a:visited {
|
||||||
|
color: var(--color-link-visited);
|
||||||
|
}
|
||||||
|
|
||||||
|
a[href^="#"]:visited {
|
||||||
|
color: var(--color-link);
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
details {
|
details {
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
border: 2px solid var(--color-text);
|
border: 2px solid var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
summary:hover {
|
summary:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*mathML*/
|
/* Math */
|
||||||
.htmlmathparagraph, mtext,math {
|
.htmlmathparagraph,
|
||||||
|
math,
|
||||||
|
mtext {
|
||||||
font-family: Lete Sans Math;
|
font-family: Lete Sans Math;
|
||||||
}
|
}
|
||||||
.math-container,
|
|
||||||
#math-container {
|
#math-container,
|
||||||
|
.math-container {
|
||||||
display: block;
|
display: block;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
padding: .5em;
|
padding: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.equation {
|
.equation {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1fr) auto;
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
column-gap: 1em;
|
column-gap: 1em;
|
||||||
margin: .5em 0;
|
margin: 0.5em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.equation .math-container {
|
.equation .math-container {
|
||||||
@@ -64,10 +88,11 @@ summary:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.equation-number {
|
.equation-number {
|
||||||
white-space: nowrap;
|
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Text */
|
||||||
.text-space .langtag {
|
.text-space .langtag {
|
||||||
color: var(--color-tag1);
|
color: var(--color-tag1);
|
||||||
}
|
}
|
||||||
@@ -76,86 +101,69 @@ summary:hover {
|
|||||||
font-variant-caps: small-caps;
|
font-variant-caps: small-caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.uri,
|
||||||
a.url {
|
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;
|
overflow-wrap: break-word;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.post-list {
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
color: var(--color-text);
|
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
text-align: right;
|
|
||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagetitle {
|
.pagetitle {
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
font-weight: normal;
|
font-weight: 400;
|
||||||
font-style: normal;
|
line-height: 1;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
line-height: 100%;
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-top: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.draft-notice {
|
||||||
|
color: var(--color-notice);
|
||||||
|
margin: 1em auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3 {
|
||||||
|
margin-top: 1em;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
margin-top: 1em;
|
|
||||||
font-size: 1.44rem;
|
font-size: 1.44rem;
|
||||||
font-weight: bold;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
margin-top: 1em;
|
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
font-weight: bold;
|
|
||||||
font-style: normal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
margin-top: 1em;
|
|
||||||
font-size: 1rem;
|
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 {
|
section.body {
|
||||||
@@ -167,18 +175,17 @@ section.body {
|
|||||||
line-height: normal;
|
line-height: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* table. copied from https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/table */
|
/* Tables */
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
border: 2px solid rgb(140 140 140);
|
border: 2px solid rgb(140 140 140);
|
||||||
font-size: 0.8rem;
|
font-size: 1rem;
|
||||||
letter-spacing: 1px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
caption {
|
caption {
|
||||||
caption-side: bottom;
|
caption-side: bottom;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
font-weight: bold;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
thead,
|
thead,
|
||||||
@@ -205,161 +212,149 @@ tfoot th {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tfoot td {
|
tfoot td {
|
||||||
font-weight: bold;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Media */
|
||||||
figure {
|
figure {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
padding: 5px;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 80%;
|
max-width: 80%;
|
||||||
|
margin: auto;
|
||||||
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.centerimg img {
|
.centerimg img {
|
||||||
margin: 0 auto 0 auto;
|
|
||||||
display: block;
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.highlight,
|
||||||
div.highlight,
|
|
||||||
pre code {
|
pre code {
|
||||||
|
display: block;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
display: block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
font-family: "IosevkaC", monospace;
|
|
||||||
margin: 0 auto;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0px 2px;
|
margin: 0 auto;
|
||||||
|
padding: 0 2px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
font-family: "IosevkaC", monospace;
|
||||||
font-variant-ligatures: none;
|
font-variant-ligatures: none;
|
||||||
font-kerning: none;
|
font-kerning: none;
|
||||||
text-rendering: optimizeSpeed;
|
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 {
|
.gallery {
|
||||||
margin-top: 2em;
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
margin-top: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gallery img {
|
.gallery img {
|
||||||
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 320px;
|
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;
|
|
||||||
} */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Layout */
|
||||||
.toc {
|
.toc {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sidebar. no sidenotes */
|
@media (max-width: 768px) {
|
||||||
|
body {
|
||||||
|
max-width: var(--mobile-max-width);
|
||||||
|
margin: auto;
|
||||||
|
padding: 0 5%;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
mjx-container[display="true"] {
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 769px) {
|
@media (min-width: 769px) {
|
||||||
body {
|
body {
|
||||||
max-width: 1350px;
|
display: flex;
|
||||||
display: -webkit-flex;
|
|
||||||
-webkit-flex-flow: row wrap;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
-ms-flex-flow: row wrap;
|
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
width: 95%;
|
width: 95%;
|
||||||
padding-right: 5%;
|
max-width: var(--layout-max-width);
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
padding-right: 5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc {
|
.toc {
|
||||||
|
display: block;
|
||||||
|
width: var(--toc-width);
|
||||||
margin-top: 5rem;
|
margin-top: 5rem;
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
width: 33%;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div#contents ul,
|
#contents ul,
|
||||||
div#contents-big ul {
|
#contents-big ul {
|
||||||
margin-top: 0.5em;
|
list-style: none;
|
||||||
margin-bottom: 0.5em;
|
margin: 0.5em 0;
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
list-style-type: decimal;
|
|
||||||
margin-left: 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div#contents-big ul ul {
|
#contents-big li + li {
|
||||||
list-style-type: none;
|
margin-top: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#contents-big li+li {
|
#contents-big .toc-section-number {
|
||||||
margin-top: 0.5em
|
margin-right: 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#contents-big {
|
#contents-big {
|
||||||
font-size: 80%;
|
|
||||||
padding-top: 0;
|
|
||||||
padding-left: 1rem;
|
|
||||||
text-align: left;
|
|
||||||
max-width: 60%;
|
|
||||||
clear: both;
|
|
||||||
margin-right: 4em;
|
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 5rem;
|
top: 5rem;
|
||||||
left: 100%
|
left: 100%;
|
||||||
|
clear: both;
|
||||||
|
max-width: 60%;
|
||||||
|
margin-right: 4em;
|
||||||
|
padding-left: 1rem;
|
||||||
|
font-size: 80%;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#contents-big .mini-header {
|
#contents-big .mini-header {
|
||||||
font-weight: bold;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-variant: small-caps;
|
font-variant: small-caps;
|
||||||
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-space {
|
.text-space {
|
||||||
display: inline-block;
|
|
||||||
width: 66%;
|
width: 66%;
|
||||||
max-width: 800px;
|
max-width: var(--content-max-width);
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* sidebar+sidenotes */
|
|
||||||
|
@media (min-width: 769px) and (max-width: 1199px) {
|
||||||
|
.toc {
|
||||||
|
flex: 0 0 var(--toc-width-no-sidenotes);
|
||||||
|
width: var(--toc-width-no-sidenotes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#contents-big {
|
||||||
|
max-width: none;
|
||||||
|
margin-right: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-space {
|
||||||
|
flex: 1 1 0;
|
||||||
|
width: auto;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
@media (min-width: 1200px) {
|
||||||
body {
|
body {
|
||||||
width: 75%;
|
width: 75%;
|
||||||
@@ -368,7 +363,6 @@ code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
|
|
||||||
.no-print,
|
.no-print,
|
||||||
.no-print * {
|
.no-print * {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ body {
|
|||||||
position: relative;
|
position: relative;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
@media (max-width: 1200px) {
|
@media (max-width: 1199px) {
|
||||||
.sidenote,
|
.sidenote,
|
||||||
.marginnote,
|
.marginnote,
|
||||||
.marginnote-left {
|
.marginnote-left {
|
||||||
@@ -142,7 +142,7 @@ label.margin-toggle:not(.sidenote-number) {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1200px) {
|
@media (max-width: 1199px) {
|
||||||
label.margin-toggle:not(.sidenote-number) {
|
label.margin-toggle:not(.sidenote-number) {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,3 +20,4 @@
|
|||||||
\newcommand{\del}{\setminus}
|
\newcommand{\del}{\setminus}
|
||||||
\newcommand{\con}{/}
|
\newcommand{\con}{/}
|
||||||
\newcommand{\minor}{\times}
|
\newcommand{\minor}{\times}
|
||||||
|
\newcommand{\FF}{\mathbb{F}}
|
||||||
|
|||||||
@@ -25,13 +25,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="text-space">
|
<div class="text-space">
|
||||||
<header class="no-print">
|
<header class="no-print">
|
||||||
<nav>
|
$title$
|
||||||
<a href="/">Home</a>
|
|
||||||
</nav>
|
|
||||||
</header>
|
</header>
|
||||||
<main role="main">
|
<main role="main">
|
||||||
<h1 class="pagetitle">$title$</h1>
|
<article>
|
||||||
|
<section class="body">
|
||||||
$body$
|
$body$
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
</main>
|
</main>
|
||||||
<footer></footer>
|
<footer></footer>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
<article>
|
|
||||||
<section class="body">
|
|
||||||
$body$
|
|
||||||
</section>
|
|
||||||
</article>
|
|
||||||
116
src/ChaoDoc.hs
116
src/ChaoDoc.hs
@@ -1,13 +1,23 @@
|
|||||||
{-# LANGUAGE BlockArguments #-}
|
{-# LANGUAGE BlockArguments #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE StandaloneKindSignatures #-}
|
||||||
|
|
||||||
module ChaoDoc (chaoDocRead, chaoDocWrite, chaoDocPandocCompiler, chaoDocCompiler) where
|
module ChaoDoc
|
||||||
|
( ChaoDocFiles (..),
|
||||||
|
chaoDocRead,
|
||||||
|
chaoDocWrite,
|
||||||
|
chaoDocPandocCompiler,
|
||||||
|
chaoDocCompiler,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
import Control.Monad (guard)
|
import Control.Monad (guard)
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
|
import qualified Control.Monad.State.Strict as Strict
|
||||||
import Data.Char (isSpace)
|
import Data.Char (isSpace)
|
||||||
import Data.Either
|
import Data.Either
|
||||||
import Data.Functor
|
import Data.Functor
|
||||||
|
import Data.Kind (Type)
|
||||||
import Data.List (find)
|
import Data.List (find)
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
@@ -16,19 +26,16 @@ import qualified Data.Text as T
|
|||||||
import Hakyll
|
import Hakyll
|
||||||
import Pangu (isCJK, pangu)
|
import Pangu (isCJK, pangu)
|
||||||
import SideNoteHTML (usingSideNotesHTML)
|
import SideNoteHTML (usingSideNotesHTML)
|
||||||
import System.IO.Unsafe
|
|
||||||
import Text.Pandoc
|
import Text.Pandoc
|
||||||
-- import Text.Pandoc.Builder
|
-- import Text.Pandoc.Builder
|
||||||
import Text.Pandoc.Walk (query, walk, walkM)
|
import Text.Pandoc.Walk (query, walk, walkM)
|
||||||
|
|
||||||
cslFile :: String
|
type ChaoDocFiles :: Type
|
||||||
cslFile = "assets/bib_style.csl"
|
data ChaoDocFiles = ChaoDocFiles
|
||||||
|
{ chaoDocCslFile :: FilePath,
|
||||||
bibFile :: String
|
chaoDocBibFile :: FilePath,
|
||||||
bibFile = "ref.bib"
|
chaoDocMacroFile :: FilePath
|
||||||
|
}
|
||||||
macroFile :: String
|
|
||||||
macroFile = "assets/math-macros.tex"
|
|
||||||
|
|
||||||
-- On mac, please do `export LANG=C` before using this thing
|
-- On mac, please do `export LANG=C` before using this thing
|
||||||
chaoDocRead :: ReaderOptions
|
chaoDocRead :: ReaderOptions
|
||||||
@@ -52,23 +59,23 @@ chaoDocWrite =
|
|||||||
writerTOCDepth = 2
|
writerTOCDepth = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
chaoDocPandocCompiler :: Compiler (Item Pandoc)
|
chaoDocPandocCompiler :: ChaoDocFiles -> Compiler (Item Pandoc)
|
||||||
chaoDocPandocCompiler = do
|
chaoDocPandocCompiler paths = do
|
||||||
macros <- T.pack <$> loadBody (fromFilePath macroFile)
|
macros <- T.pack <$> loadBody (fromFilePath $ chaoDocMacroFile paths)
|
||||||
csl <- load $ fromFilePath cslFile
|
csl <- load $ fromFilePath $ chaoDocCslFile paths
|
||||||
bib <- load $ fromFilePath bibFile
|
bib <- load $ fromFilePath $ chaoDocBibFile paths
|
||||||
body <- getResourceBody
|
body <- getResourceBody
|
||||||
let bodyWithMacros =
|
let bodyWithMacros =
|
||||||
fmap (T.unpack . prependMacros macros . normalizeTheoremFenceTitles . T.pack) body
|
fmap (T.unpack . prependMacros macros . normalizeTheoremFenceTitles . T.pack) body
|
||||||
prepare =
|
prepare =
|
||||||
addMeta "link-citations" (MetaBool True)
|
addMeta "link-citations" (MetaBool True)
|
||||||
. addMeta "reference-section-title" (MetaInlines [Str "References"])
|
. addMeta "reference-section-title" (MetaInlines [Str "References"])
|
||||||
. myFilter
|
. myFilter macros
|
||||||
readPandocWith chaoDocRead bodyWithMacros
|
readPandocWith chaoDocRead bodyWithMacros
|
||||||
>>= processPandocBiblio csl bib . fmap prepare
|
>>= processPandocBiblio csl bib . fmap prepare
|
||||||
|
|
||||||
chaoDocCompiler :: Compiler (Item String)
|
chaoDocCompiler :: ChaoDocFiles -> Compiler (Item String)
|
||||||
chaoDocCompiler = chaoDocPandocCompiler <&> writePandocWith chaoDocWrite
|
chaoDocCompiler paths = chaoDocPandocCompiler paths <&> writePandocWith chaoDocWrite
|
||||||
|
|
||||||
addMeta :: T.Text -> MetaValue -> Pandoc -> Pandoc
|
addMeta :: T.Text -> MetaValue -> Pandoc -> Pandoc
|
||||||
addMeta name value (Pandoc meta a) =
|
addMeta name value (Pandoc meta a) =
|
||||||
@@ -77,8 +84,8 @@ addMeta name value (Pandoc meta a) =
|
|||||||
newMeta = Meta newMap
|
newMeta = Meta newMap
|
||||||
in Pandoc newMeta a
|
in Pandoc newMeta a
|
||||||
|
|
||||||
myFilter :: Pandoc -> Pandoc
|
myFilter :: Text -> Pandoc -> Pandoc
|
||||||
myFilter = usingSideNotesHTML chaoDocWrite . theoremFilter . panguFilter . equationFilter
|
myFilter macros = usingSideNotesHTML chaoDocWrite . theoremFilter macros . panguFilter . equationFilter
|
||||||
|
|
||||||
pandocToInline :: Pandoc -> [Inline]
|
pandocToInline :: Pandoc -> [Inline]
|
||||||
pandocToInline (Pandoc _ blocks) = go (reverse blocks)
|
pandocToInline (Pandoc _ blocks) = go (reverse blocks)
|
||||||
@@ -99,7 +106,8 @@ incrementalBlock =
|
|||||||
"Proposition",
|
"Proposition",
|
||||||
"Corollary",
|
"Corollary",
|
||||||
"Observation",
|
"Observation",
|
||||||
"Figure"
|
"Figure",
|
||||||
|
"Table"
|
||||||
]
|
]
|
||||||
|
|
||||||
otherBlock :: [Text]
|
otherBlock :: [Text]
|
||||||
@@ -184,8 +192,9 @@ normalizeTheoremClass :: Attr -> Text -> Attr
|
|||||||
normalizeTheoremClass (ident, classes, attrs) theoremType =
|
normalizeTheoremClass (ident, classes, attrs) theoremType =
|
||||||
(ident, theoremType : filter ((`notElem` theoremClasses) . normalizeBlockClass) classes, attrs)
|
(ident, theoremType : filter ((`notElem` theoremClasses) . normalizeBlockClass) classes, attrs)
|
||||||
|
|
||||||
theoremFilter :: Pandoc -> Pandoc
|
theoremFilter :: Text -> Pandoc -> Pandoc
|
||||||
theoremFilter doc = walk makeTheorem $ autorefFilter $ evalState (walkM preprocessTheorems doc) 1
|
theoremFilter macros doc =
|
||||||
|
walk (makeTheorem macros) $ autorefFilter $ evalState (walkM preprocessTheorems doc) 1
|
||||||
|
|
||||||
-- [index, type, idx]
|
-- [index, type, idx]
|
||||||
theoremIndex :: Block -> [(Text, (Text, Text))]
|
theoremIndex :: Block -> [(Text, (Text, Text))]
|
||||||
@@ -214,7 +223,41 @@ autoref _ y = y
|
|||||||
autorefFilter :: Pandoc -> Pandoc
|
autorefFilter :: Pandoc -> Pandoc
|
||||||
autorefFilter x = walk (autoref links) x
|
autorefFilter x = walk (autoref links) x
|
||||||
where
|
where
|
||||||
links = query theoremIndex x
|
links = query theoremIndex x ++ sectionIndex x
|
||||||
|
|
||||||
|
sectionIndex :: Pandoc -> [(Text, (Text, Text))]
|
||||||
|
sectionIndex doc = snd $ Strict.execState (walkM collectSectionIndex doc) ([], [])
|
||||||
|
|
||||||
|
collectSectionIndex :: Block -> Strict.State ([Int], [(Text, (Text, Text))]) Block
|
||||||
|
collectSectionIndex header@(Header level attr@(ident, _, _) _)
|
||||||
|
| isNumberedSectionHeader attr = do
|
||||||
|
(curNums, refs) <- Strict.get
|
||||||
|
let nextNums = nextSectionNumbers level curNums
|
||||||
|
refs'
|
||||||
|
| isSectionIdentifier ident = (ident, ("Section", renderSectionNumber nextNums)) : refs
|
||||||
|
| otherwise = refs
|
||||||
|
Strict.put (nextNums, refs')
|
||||||
|
pure header
|
||||||
|
collectSectionIndex block = pure block
|
||||||
|
|
||||||
|
isNumberedSectionHeader :: Attr -> Bool
|
||||||
|
isNumberedSectionHeader (_, classes, _) = "unnumbered" `notElem` classes
|
||||||
|
|
||||||
|
isSectionIdentifier :: Text -> Bool
|
||||||
|
isSectionIdentifier = T.isPrefixOf "sec:"
|
||||||
|
|
||||||
|
nextSectionNumbers :: Int -> [Int] -> [Int]
|
||||||
|
nextSectionNumbers level nums =
|
||||||
|
reverse $ bumpLast $ reverse prefix
|
||||||
|
where
|
||||||
|
prefix = take level (nums ++ repeat 0)
|
||||||
|
|
||||||
|
bumpLast :: [Int] -> [Int]
|
||||||
|
bumpLast [] = [1]
|
||||||
|
bumpLast (x : xs) = (x + 1) : xs
|
||||||
|
|
||||||
|
renderSectionNumber :: [Int] -> Text
|
||||||
|
renderSectionNumber = T.intercalate "." . map (pack . show)
|
||||||
|
|
||||||
equationFilter :: Pandoc -> Pandoc
|
equationFilter :: Pandoc -> Pandoc
|
||||||
equationFilter doc = walk (equationAutoref links) processed
|
equationFilter doc = walk (equationAutoref links) processed
|
||||||
@@ -281,27 +324,16 @@ equationAutoref x (Cite citations inlines)
|
|||||||
linkTitle = "Eq. (" <> num <> ")"
|
linkTitle = "Eq. (" <> num <> ")"
|
||||||
equationAutoref _ y = y
|
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 :: Text -> Text -> Text
|
||||||
prependMacros macros body = macros <> "\n\n" <> body
|
prependMacros macros body = macros <> "\n\n" <> body
|
||||||
|
|
||||||
prependMathMacros :: Text -> Text
|
thmNamePandoc :: Text -> Text -> Pandoc
|
||||||
prependMathMacros = prependMacros mathMacros
|
thmNamePandoc macros x =
|
||||||
|
|
||||||
thmNamePandoc :: Text -> Pandoc
|
|
||||||
thmNamePandoc x =
|
|
||||||
fromRight (Pandoc nullMeta []) . runPure $
|
fromRight (Pandoc nullMeta []) . runPure $
|
||||||
readMarkdown chaoDocRead (prependMathMacros x)
|
readMarkdown chaoDocRead (prependMacros macros x)
|
||||||
|
|
||||||
makeTheorem :: Block -> Block
|
makeTheorem :: Text -> Block -> Block
|
||||||
makeTheorem (Div attr xs)
|
makeTheorem macros (Div attr xs)
|
||||||
| isNothing t = Div attr xs
|
| isNothing t = Div attr xs
|
||||||
| otherwise = Div (addClass attr "theorem-environment") (Plain [header] : xs)
|
| otherwise = Div (addClass attr "theorem-environment") (Plain [header] : xs)
|
||||||
where
|
where
|
||||||
@@ -318,8 +350,8 @@ makeTheorem (Div attr xs)
|
|||||||
nametext =
|
nametext =
|
||||||
if isNothing name
|
if isNothing name
|
||||||
then Str ""
|
then Str ""
|
||||||
else Span (addClass nullAttr "name") (pandocToInline $ thmNamePandoc $ fromJust name)
|
else Span (addClass nullAttr "name") (pandocToInline $ thmNamePandoc macros $ fromJust name)
|
||||||
makeTheorem x = x
|
makeTheorem _ x = x
|
||||||
|
|
||||||
-- pangu filter
|
-- pangu filter
|
||||||
lastChar :: Inline -> Maybe Char
|
lastChar :: Inline -> Maybe Char
|
||||||
|
|||||||
76
src/site.hs
76
src/site.hs
@@ -9,8 +9,46 @@ import Hakyll
|
|||||||
import System.FilePath
|
import System.FilePath
|
||||||
import Text.Pandoc
|
import Text.Pandoc
|
||||||
|
|
||||||
mds :: Pattern
|
mdfiles :: Pattern
|
||||||
mds = "main.md"
|
mdfiles = "main.md"
|
||||||
|
|
||||||
|
images :: Pattern
|
||||||
|
images = "images/**"
|
||||||
|
|
||||||
|
mathMacro :: FilePath
|
||||||
|
mathMacro = "assets/math-macros.tex"
|
||||||
|
|
||||||
|
cslfile :: FilePath
|
||||||
|
cslfile = "assets/bib_style.csl"
|
||||||
|
|
||||||
|
reference :: FilePath
|
||||||
|
reference = "ref.bib"
|
||||||
|
|
||||||
|
fonts :: Pattern
|
||||||
|
fonts = "assets/fonts/*"
|
||||||
|
|
||||||
|
favicon :: FilePath
|
||||||
|
favicon = "assets/favicon.ico"
|
||||||
|
|
||||||
|
css :: Pattern
|
||||||
|
css = "assets/css/*"
|
||||||
|
|
||||||
|
templatesPattern :: Pattern
|
||||||
|
templatesPattern = "assets/templates/*"
|
||||||
|
|
||||||
|
templateDefault :: Identifier
|
||||||
|
templateDefault = fromFilePath "assets/templates/default.html"
|
||||||
|
|
||||||
|
templatePostlist :: Identifier
|
||||||
|
templatePostlist = fromFilePath "assets/templates/post-list.html"
|
||||||
|
|
||||||
|
chaoDocFiles :: ChaoDocFiles
|
||||||
|
chaoDocFiles =
|
||||||
|
ChaoDocFiles
|
||||||
|
{ chaoDocCslFile = cslfile,
|
||||||
|
chaoDocBibFile = reference,
|
||||||
|
chaoDocMacroFile = mathMacro
|
||||||
|
}
|
||||||
|
|
||||||
config :: Configuration
|
config :: Configuration
|
||||||
config =
|
config =
|
||||||
@@ -22,52 +60,51 @@ config =
|
|||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = hakyllWith config $ do
|
main = hakyllWith config $ do
|
||||||
match "images/**" $ do
|
match images $ do
|
||||||
route idRoute
|
route idRoute
|
||||||
compile copyFileCompiler
|
compile copyFileCompiler
|
||||||
|
|
||||||
match "assets/math-macros.tex" $ compile getResourceBody
|
match (fromGlob mathMacro) $ compile getResourceBody
|
||||||
|
|
||||||
match "assets/bib_style.csl" $ compile cslCompiler
|
match (fromGlob cslfile) $ compile cslCompiler
|
||||||
|
|
||||||
match "ref.bib" $ compile biblioCompiler
|
match (fromGlob reference) $ compile biblioCompiler
|
||||||
|
|
||||||
match "assets/fonts/*" $ do
|
match fonts $ do
|
||||||
route $ gsubRoute "assets/fonts/" (const "fonts/")
|
route $ gsubRoute "assets/fonts/" (const "fonts/")
|
||||||
compile copyFileCompiler
|
compile copyFileCompiler
|
||||||
|
|
||||||
match "assets/favicon.ico" $ do
|
match (fromGlob favicon) $ do
|
||||||
route $ constRoute "favicon.ico"
|
route $ constRoute "favicon.ico"
|
||||||
compile copyFileCompiler
|
compile copyFileCompiler
|
||||||
|
|
||||||
match "assets/css/*" $ do
|
match css $ do
|
||||||
route $ gsubRoute "assets/css/" (const "css/")
|
route $ gsubRoute "assets/css/" (const "css/")
|
||||||
compile compressCssCompiler
|
compile compressCssCompiler
|
||||||
|
|
||||||
match mds $ do
|
match mdfiles $ do
|
||||||
route $ setExtension "html"
|
route $ setExtension "html"
|
||||||
compile $ do
|
compile $ do
|
||||||
tocCtx <- getTocCtx defaultContext
|
tocCtx <- getTocCtx defaultContext
|
||||||
chaoDocCompiler
|
chaoDocCompiler chaoDocFiles
|
||||||
>>= loadAndApplyTemplate "assets/templates/post.html" tocCtx
|
>>= loadAndApplyTemplate templateDefault tocCtx
|
||||||
>>= loadAndApplyTemplate "assets/templates/default.html" tocCtx
|
|
||||||
>>= relativizeUrls
|
>>= relativizeUrls
|
||||||
|
|
||||||
create ["index.html"] $ do
|
create ["index.html"] $ do
|
||||||
route idRoute
|
route idRoute
|
||||||
compile $ do
|
compile $ do
|
||||||
posts <- loadAll mds
|
posts <- loadAll mdfiles
|
||||||
let indexCtx =
|
let indexCtx =
|
||||||
constField "title" "Notes"
|
constField "title" ""
|
||||||
`mappend` constField "toc" ""
|
`mappend` constField "toc" ""
|
||||||
`mappend` listField "posts" postCtx (return posts)
|
`mappend` listField "posts" postCtx (return posts)
|
||||||
`mappend` defaultContext
|
`mappend` defaultContext
|
||||||
makeItem ""
|
makeItem ""
|
||||||
>>= loadAndApplyTemplate "assets/templates/post-list.html" indexCtx
|
>>= loadAndApplyTemplate templatePostlist indexCtx
|
||||||
>>= loadAndApplyTemplate "assets/templates/default.html" indexCtx
|
>>= loadAndApplyTemplate templateDefault indexCtx
|
||||||
>>= relativizeUrls
|
>>= relativizeUrls
|
||||||
|
|
||||||
match "assets/templates/*" $ compile templateBodyCompiler
|
match templatesPattern $ compile templateBodyCompiler
|
||||||
|
|
||||||
postCtx :: Context String
|
postCtx :: Context String
|
||||||
postCtx =
|
postCtx =
|
||||||
@@ -80,7 +117,7 @@ getTocCtx :: Context a -> Compiler (Context a)
|
|||||||
getTocCtx ctx = do
|
getTocCtx ctx = do
|
||||||
noToc <- (Just "true" ==) <$> (getUnderlying >>= (`getMetadataField` "no-toc"))
|
noToc <- (Just "true" ==) <$> (getUnderlying >>= (`getMetadataField` "no-toc"))
|
||||||
writerOpts <- mkTocWriter defaultHakyllWriterOptions
|
writerOpts <- mkTocWriter defaultHakyllWriterOptions
|
||||||
toc <- writePandocWith writerOpts <$> chaoDocPandocCompiler
|
toc <- writePandocWith writerOpts <$> chaoDocPandocCompiler chaoDocFiles
|
||||||
pure $
|
pure $
|
||||||
mconcat
|
mconcat
|
||||||
[ ctx,
|
[ ctx,
|
||||||
@@ -94,6 +131,7 @@ getTocCtx ctx = do
|
|||||||
pure $
|
pure $
|
||||||
writerOpts
|
writerOpts
|
||||||
{ writerTableOfContents = True,
|
{ writerTableOfContents = True,
|
||||||
|
writerNumberSections = True,
|
||||||
writerTOCDepth = 2,
|
writerTOCDepth = 2,
|
||||||
writerTemplate = tmpl,
|
writerTemplate = tmpl,
|
||||||
writerHTMLMathMethod = MathML
|
writerHTMLMathMethod = MathML
|
||||||
|
|||||||
Reference in New Issue
Block a user