Compare commits
3 Commits
modern_the
...
3d2c5a8852
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d2c5a8852 | |||
| 614de591ba | |||
| 71611b0641 |
@@ -1,130 +1,89 @@
|
||||
.theorem-environment {
|
||||
position: relative;
|
||||
margin: 1.5rem 0;
|
||||
padding: 1rem 1.25rem;
|
||||
background-color: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 1rem;
|
||||
box-shadow: var(--color-shadow-soft);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.theorem-environment > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.theorem-environment > :last-child {
|
||||
margin-bottom: 0;
|
||||
margin-top: 1em;
|
||||
padding: 0.5em;
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
.theorem-header {
|
||||
color: var(--color-text);
|
||||
font-weight: 700;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.theorem-header .index:before {
|
||||
content: " ";
|
||||
content: ' ';
|
||||
}
|
||||
|
||||
.theorem-header .name:before {
|
||||
content: " (";
|
||||
content: ' (';
|
||||
}
|
||||
|
||||
.theorem-header .name:after {
|
||||
content: ")";
|
||||
content: ')';
|
||||
}
|
||||
|
||||
.theorem-header:after {
|
||||
content: ".\2002\2002";
|
||||
content: '.\2002\2002';
|
||||
}
|
||||
|
||||
.theorem-header+p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.Proof {
|
||||
padding-right: 2.5rem;
|
||||
font-style: normal;
|
||||
.Proof .type {
|
||||
font-style: italic;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.Proof .type {
|
||||
color: var(--color-linkh);
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
.Proof {
|
||||
font-style: normal;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.Proof:after {
|
||||
content: "\220e";
|
||||
content: '∎';
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
bottom: 0.85rem;
|
||||
color: var(--color-tag1);
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
table.postindex {
|
||||
width: 100%;
|
||||
border: 0;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
table.postindex cite {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
table.postindex td {
|
||||
padding: 0.65rem 0;
|
||||
border: 0;
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
table.postindex tr:nth-child(even) td {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
table.postindex tr:last-child td {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
table.postindex td.right {
|
||||
width: 11ex;
|
||||
color: var(--color-tag1);
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
width: 11ex;
|
||||
}
|
||||
|
||||
.header-section-number {
|
||||
margin-right: 0.55rem;
|
||||
color: var(--color-tag1);
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.header-section-number:after {
|
||||
content: ".";
|
||||
content: '.';
|
||||
}
|
||||
|
||||
.csl-entry {
|
||||
display: table;
|
||||
width: 100%;
|
||||
margin-bottom: 0.75rem;
|
||||
table-layout: auto;
|
||||
}
|
||||
|
||||
.csl-left-margin {
|
||||
display: table-cell;
|
||||
width: 1px;
|
||||
padding-right: 0.75em;
|
||||
color: var(--color-tag1);
|
||||
padding-right: 0.5em;
|
||||
white-space: nowrap;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.csl-right-inline {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.csl-right-inline a{
|
||||
word-break: break-all;
|
||||
}
|
||||
603
css/default.css
603
css/default.css
@@ -1,170 +1,69 @@
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--color-text: #162031;
|
||||
--color-tag1: #6c788c;
|
||||
--color-tag2: #547157;
|
||||
--color-bg: #f3f6fb;
|
||||
--color-surface: rgba(255, 255, 255, 0.84);
|
||||
--color-surface-strong: #ffffff;
|
||||
--color-surface-muted: #edf3fb;
|
||||
--color-border: rgba(22, 32, 49, 0.12);
|
||||
--color-border-strong: rgba(22, 32, 49, 0.2);
|
||||
--color-link: #225b9c;
|
||||
--color-link-line: rgba(34, 91, 156, 0.28);
|
||||
--color-linkhbg: rgba(89, 143, 211, 0.16);
|
||||
--color-linkh: #163a63;
|
||||
--color-bq: #628b72;
|
||||
--color-notice: #d0455a;
|
||||
--color-shadow: 0 20px 50px rgba(15, 23, 42, 0.08);
|
||||
--color-shadow-soft: 0 10px 30px rgba(15, 23, 42, 0.06);
|
||||
--code-bg: #f6f8fc;
|
||||
--code-border: rgba(55, 65, 81, 0.14);
|
||||
--page-glow-1: rgba(144, 187, 241, 0.18);
|
||||
--page-glow-2: rgba(99, 141, 118, 0.14);
|
||||
--color-text: black;
|
||||
--color-tag1: gray;
|
||||
--color-tag2: darkolivegreen;
|
||||
--color-bg: white;
|
||||
--color-link: #337ab7;
|
||||
--color-linkhbg: #e6f0ff;
|
||||
--color-linkh: #002266;
|
||||
--color-bq: olivedrab;
|
||||
--color-notice: #fb4f4f;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
--color-text: #e7edf7;
|
||||
--color-tag1: #9aa7bb;
|
||||
--color-tag2: #9abf9c;
|
||||
--color-bg: #0b1020;
|
||||
--color-surface: rgba(15, 23, 42, 0.78);
|
||||
--color-surface-strong: #101827;
|
||||
--color-surface-muted: #162238;
|
||||
--color-border: rgba(148, 163, 184, 0.18);
|
||||
--color-border-strong: rgba(148, 163, 184, 0.26);
|
||||
--color-link: #8bc3ff;
|
||||
--color-link-line: rgba(139, 195, 255, 0.35);
|
||||
--color-linkhbg: rgba(139, 195, 255, 0.16);
|
||||
--color-linkh: #d9ecff;
|
||||
--color-bq: #8db59a;
|
||||
--color-notice: #ff8b8b;
|
||||
--color-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
|
||||
--color-shadow-soft: 0 12px 32px rgba(0, 0, 0, 0.3);
|
||||
--code-bg: #0f172a;
|
||||
--code-border: rgba(148, 163, 184, 0.22);
|
||||
--page-glow-1: rgba(71, 119, 183, 0.22);
|
||||
--page-glow-2: rgba(74, 118, 90, 0.18);
|
||||
--color-text: white;
|
||||
--color-bg: black;
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
scrollbar-gutter: stable;
|
||||
scroll-behavior: smooth;
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
body {
|
||||
box-sizing: content-box;
|
||||
margin: 0;
|
||||
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-weight: 400;
|
||||
font-style: normal;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
line-height: 140%;
|
||||
color: var(--color-text);
|
||||
background:
|
||||
radial-gradient(circle at top, var(--page-glow-1), transparent 38%),
|
||||
radial-gradient(circle at right top, var(--page-glow-2), transparent 30%),
|
||||
var(--color-bg);
|
||||
background-attachment: fixed;
|
||||
background-color: var(--color-bg);
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
body.lang-zh {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background-color: var(--color-linkhbg);
|
||||
color: var(--color-linkh);
|
||||
}
|
||||
|
||||
main,
|
||||
.text-space {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
body a {
|
||||
color: var(--color-link);
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: 0.08em;
|
||||
text-underline-offset: 0.18em;
|
||||
text-decoration-color: var(--color-link-line);
|
||||
transition:
|
||||
color 0.18s ease,
|
||||
background-color 0.18s ease,
|
||||
text-decoration-color 0.18s ease;
|
||||
-webkit-box-decoration-break: clone;
|
||||
box-decoration-break: clone;
|
||||
}
|
||||
|
||||
body a:visited {
|
||||
color: var(--color-link);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.text-space a:hover {
|
||||
background-color: var(--color-linkhbg);
|
||||
color: var(--color-linkh);
|
||||
text-decoration-color: transparent;
|
||||
border-radius: 0.2rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
body a:focus-visible {
|
||||
outline: 2px solid var(--color-link);
|
||||
outline-offset: 3px;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
details {
|
||||
margin: 1.25rem 0;
|
||||
padding: 0.85rem 1rem;
|
||||
background-color: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 1rem;
|
||||
box-shadow: var(--color-shadow-soft);
|
||||
background-color: var(--color-linkhbg);
|
||||
}
|
||||
|
||||
details[open] summary {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
details > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
summary:hover {
|
||||
cursor: pointer;
|
||||
color: var(--color-linkh);
|
||||
}
|
||||
|
||||
/*mathML*/
|
||||
.htmlmathparagraph,
|
||||
mtext,
|
||||
math {
|
||||
font-family: "Lete Sans Math";
|
||||
.htmlmathparagraph, mtext,math {
|
||||
font-family: Lete Sans Math;
|
||||
}
|
||||
|
||||
.math-container,
|
||||
#math-container {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
padding: 0.5em;
|
||||
padding: .5em;
|
||||
}
|
||||
|
||||
.math-container.math-container-tagged {
|
||||
@@ -173,7 +72,7 @@ math {
|
||||
align-items: center;
|
||||
column-gap: 1rem;
|
||||
overflow: visible;
|
||||
padding: 0.5em 0;
|
||||
padding: .5em 0;
|
||||
}
|
||||
|
||||
.math-container.math-container-tagged .math-tag-spacer {
|
||||
@@ -184,7 +83,7 @@ math {
|
||||
min-width: 0;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
padding: 0.5em 0;
|
||||
padding: .5em 0;
|
||||
}
|
||||
|
||||
.math-container.math-container-tagged .math-tag {
|
||||
@@ -206,7 +105,6 @@ math {
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 1rem;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
@@ -219,25 +117,21 @@ header {
|
||||
font-family: "IosevkaC", sans-serif;
|
||||
}
|
||||
|
||||
/* top bar*/
|
||||
.navbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.navright {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.navright a {
|
||||
margin: 0 0 0 1em;
|
||||
}
|
||||
|
||||
/* Links inside the navbar */
|
||||
.navbar a {
|
||||
color: var(--color-text);
|
||||
text-decoration: none;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.navbar a:visited {
|
||||
@@ -245,32 +139,37 @@ header {
|
||||
}
|
||||
|
||||
nav {
|
||||
margin-bottom: 1.5rem;
|
||||
padding-bottom: 0.75rem;
|
||||
text-align: right;
|
||||
border-bottom: 1px solid var(--color-border-strong);
|
||||
border-bottom: solid 1px var(--color-text);
|
||||
}
|
||||
|
||||
nav a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
font-size: 1.2rem;
|
||||
/*margin-left: 0.5em;*/
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
font-size: 1.05rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.uri {
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
word-wrap: break-word;
|
||||
/* Legacy support */
|
||||
overflow-wrap: break-word;
|
||||
/* Modern property */
|
||||
word-break: break-all;
|
||||
/* Break long words if necessary */
|
||||
white-space: normal;
|
||||
/* Allow wrapping */
|
||||
}
|
||||
|
||||
|
||||
|
||||
footer {
|
||||
margin-top: 3rem;
|
||||
padding-right: 0.2rem;
|
||||
color: var(--color-tag1);
|
||||
font-size: 0.82rem;
|
||||
color: var(--color-text);
|
||||
font-size: 0.8rem;
|
||||
margin-top: 2em;
|
||||
text-align: right;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
h1,
|
||||
@@ -280,63 +179,47 @@ h4,
|
||||
h5,
|
||||
h6 {
|
||||
text-align: left;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.pagetitle {
|
||||
margin: 0;
|
||||
font-size: 2rem;
|
||||
font-weight: 400;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
text-align: left;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.03em;
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
margin-top: 1em;
|
||||
font-size: 1.44rem;
|
||||
font-weight: 700;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
line-height: 1.1;
|
||||
letter-spacing: -0.02em;
|
||||
text-align: left;
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 1.75rem;
|
||||
margin-bottom: 0.7rem;
|
||||
margin-top: 1em;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
line-height: 1.2;
|
||||
font-weight: bold;
|
||||
font-style: normal
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 0.6rem;
|
||||
margin-top: 1em;
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top: 1.35rem;
|
||||
margin-bottom: 0.55rem;
|
||||
line-height: 1.3;
|
||||
font-weight: bold;
|
||||
font-style: normal
|
||||
}
|
||||
|
||||
article .header {
|
||||
color: var(--color-tag1);
|
||||
font-size: 1rem;
|
||||
font-style: normal;
|
||||
color: var(--color-tag1);
|
||||
text-align: left;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
|
||||
.info {
|
||||
color: var(--color-tag2);
|
||||
font-size: 1rem;
|
||||
@@ -356,375 +239,216 @@ article .header {
|
||||
}
|
||||
|
||||
section.body {
|
||||
margin-top: 1.75rem;
|
||||
}
|
||||
|
||||
section.body > :first-child {
|
||||
margin-top: 0;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.ascii-art {
|
||||
overflow-x: auto;
|
||||
font-family: monospace;
|
||||
line-height: 1.2;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 1.5rem 0;
|
||||
padding: 1rem 1.25rem;
|
||||
background-color: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-left: 4px solid var(--color-bq);
|
||||
border-radius: 0 1rem 1rem 0;
|
||||
box-shadow: var(--color-shadow-soft);
|
||||
margin: 1rem 0;
|
||||
padding: 0 0 0 1.5em;
|
||||
border-left: 3px solid var(--color-bq);
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
margin: 0 0 1.1rem;
|
||||
ol {
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: square;
|
||||
padding-left: 2em;
|
||||
}
|
||||
.notes-list {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
.notes-list li {
|
||||
position: relative;
|
||||
padding-left: 1em;
|
||||
}
|
||||
.notes-list li::before {
|
||||
content: "-";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.3em;
|
||||
padding-left: 0.15em;
|
||||
}
|
||||
|
||||
li::marker {
|
||||
color: var(--color-tag2);
|
||||
}
|
||||
|
||||
table {
|
||||
margin: 1.5rem 0;
|
||||
border: 1px solid var(--color-border-strong);
|
||||
border-collapse: collapse;
|
||||
background-color: var(--color-surface-strong);
|
||||
box-shadow: var(--color-shadow-soft);
|
||||
margin-bottom: 0.15em;
|
||||
}
|
||||
|
||||
table,
|
||||
th,
|
||||
td {
|
||||
padding: 0.65rem 0.8rem;
|
||||
border: 1px solid var(--color-border);
|
||||
border: 1px solid darkolivegreen;
|
||||
border-collapse: collapse;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: var(--color-surface-muted);
|
||||
}
|
||||
|
||||
tr:nth-child(even) td {
|
||||
background-color: var(--color-surface);
|
||||
}
|
||||
|
||||
figure {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
gap: 0.75rem;
|
||||
padding: 0.9rem;
|
||||
margin: 1.5rem auto;
|
||||
padding: 5px;
|
||||
margin: auto;
|
||||
max-width: 80%;
|
||||
background-color: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 1.25rem;
|
||||
box-shadow: var(--color-shadow-soft);
|
||||
}
|
||||
|
||||
figure img {
|
||||
border-radius: 0.9rem;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
padding: 0 0.25rem;
|
||||
color: var(--color-tag1);
|
||||
font-size: 0.92rem;
|
||||
/* font: italic smaller sans-serif; */
|
||||
padding: 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.caption {
|
||||
display: none;
|
||||
display: none
|
||||
}
|
||||
|
||||
.centerimg img {
|
||||
margin: 0 auto 0 auto;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
pre,
|
||||
div.highlight {
|
||||
margin: 1.5rem 0;
|
||||
padding: 1rem 1.1rem;
|
||||
|
||||
div.highlight,
|
||||
pre code {
|
||||
margin: auto;
|
||||
padding: 10px;
|
||||
overflow: auto;
|
||||
background-color: var(--code-bg);
|
||||
border: 1px solid var(--code-border);
|
||||
border-radius: 1rem;
|
||||
box-shadow: var(--color-shadow-soft);
|
||||
}
|
||||
|
||||
pre code,
|
||||
div.highlight pre,
|
||||
div.highlight pre code {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
code {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
padding: 0.12em 0.35em;
|
||||
background-color: var(--code-bg);
|
||||
border: 1px solid var(--code-border);
|
||||
border-radius: 0.45rem;
|
||||
font-family: "IosevkaC", monospace;
|
||||
font-size: 0.92em;
|
||||
margin: 0 auto;
|
||||
display: inline-block;
|
||||
padding: 0px 2px;
|
||||
border-radius: 2px;
|
||||
font-variant-ligatures: none;
|
||||
font-kerning: none;
|
||||
text-rendering: optimizeSpeed;
|
||||
}
|
||||
|
||||
|
||||
.draft-notice {
|
||||
display: table;
|
||||
margin: 1.5rem auto;
|
||||
padding: 0.85rem 1rem;
|
||||
color: var(--color-notice);
|
||||
text-align: center;
|
||||
background-color: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-left: 4px solid var(--color-notice);
|
||||
border-radius: 1rem;
|
||||
box-shadow: var(--color-shadow-soft);
|
||||
margin: 1em auto;
|
||||
text-align: center
|
||||
}
|
||||
|
||||
|
||||
.subtitle {
|
||||
margin-top: 0.5rem;
|
||||
color: var(--color-tag1);
|
||||
font-size: 1.2rem;
|
||||
line-height: 1.4;
|
||||
text-align: left;
|
||||
font-size: 1.2rem;
|
||||
margin-top: 0
|
||||
}
|
||||
|
||||
.subtitle p {
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
.gallery {
|
||||
margin-top: 2em;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 1rem;
|
||||
margin-top: 2em;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.gallery img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 320px;
|
||||
border-radius: 1rem;
|
||||
box-shadow: var(--color-shadow-soft);
|
||||
display: block;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 2rem 0;
|
||||
border: 0;
|
||||
border-top: 1px solid var(--color-border-strong);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* phones: no sidebar, no sidenotes */
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
max-width: 876px;
|
||||
margin: auto;
|
||||
padding: 1rem 5% 3rem;
|
||||
text-align: left;
|
||||
background-attachment: scroll;
|
||||
}
|
||||
|
||||
mjx-container[display="true"] {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
figure {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* sidebar, no sidenotes */
|
||||
/* sidebar. no sidenotes */
|
||||
@media (min-width: 769px) {
|
||||
body {
|
||||
display: flex;
|
||||
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%;
|
||||
max-width: 1350px;
|
||||
padding-right: 5%;
|
||||
margin: auto;
|
||||
padding: 1.5rem 5% 3rem 0;
|
||||
}
|
||||
|
||||
.toc {
|
||||
display: inline-block;
|
||||
width: 33%;
|
||||
margin-top: 4.5rem;
|
||||
margin-top: 5rem;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
width: 33%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
div#contents ul,
|
||||
div#contents-big ul {
|
||||
margin-top: 0.3em;
|
||||
margin-bottom: 0.3em;
|
||||
margin-left: 0.1rem;
|
||||
padding-left: 1.45rem;
|
||||
line-height: 1.25;
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
padding-left: 1em;
|
||||
line-height: 1.2;
|
||||
list-style-type: decimal;
|
||||
margin-left: 0
|
||||
}
|
||||
|
||||
div#contents ul.notes-list,
|
||||
div#contents-big ul.notes-list {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
div#contents-big ul ul {
|
||||
list-style-type: none;
|
||||
margin-top: 0.15rem;
|
||||
margin-left: 0.2rem;
|
||||
padding-left: 0.8rem;
|
||||
border-left: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
div#contents-big li+li {
|
||||
margin-top: 0.18rem;
|
||||
}
|
||||
|
||||
div#contents-big li::marker {
|
||||
color: var(--color-tag1);
|
||||
font-family: "IosevkaC", sans-serif;
|
||||
margin-top: 0.5em
|
||||
}
|
||||
|
||||
div#contents-big {
|
||||
position: sticky;
|
||||
top: 6rem;
|
||||
max-height: calc(100vh - 7rem);
|
||||
max-height: calc(100dvh - 7rem);
|
||||
left: 100%;
|
||||
clear: both;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 68%;
|
||||
margin-right: 4em;
|
||||
padding: 0.8rem;
|
||||
background-color: var(--color-surface);
|
||||
background-clip: padding-box;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 1.25rem;
|
||||
box-shadow: var(--color-shadow-soft);
|
||||
backdrop-filter: blur(14px);
|
||||
font-size: 80%;
|
||||
padding-top: 0;
|
||||
padding-left: 1rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div#contents-big .toc-scroll {
|
||||
min-height: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
scrollbar-gutter: stable;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--color-border-strong) transparent;
|
||||
}
|
||||
|
||||
div#contents-big .toc-scroll::-webkit-scrollbar {
|
||||
width: 0.7rem;
|
||||
}
|
||||
|
||||
div#contents-big .toc-scroll::-webkit-scrollbar-track {
|
||||
margin-block: 0.45rem;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
div#contents-big .toc-scroll::-webkit-scrollbar-thumb {
|
||||
background-color: var(--color-border-strong);
|
||||
border: 0.18rem solid transparent;
|
||||
border-radius: 999px;
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
div#contents-big .toc-scroll::-webkit-scrollbar-thumb:hover {
|
||||
background-color: var(--color-tag1);
|
||||
max-width: 60%;
|
||||
clear: both;
|
||||
margin-right: 4em;
|
||||
position: sticky;
|
||||
top: 5rem;
|
||||
left: 100%
|
||||
}
|
||||
|
||||
div#contents-big .mini-header {
|
||||
margin: 0 0 0.45rem;
|
||||
color: var(--color-tag1);
|
||||
font-weight: 700;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
font-variant: small-caps;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
|
||||
div#contents-big a {
|
||||
color: var(--color-text);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
div#contents-big li > a {
|
||||
display: block;
|
||||
margin: 0 0.2rem;
|
||||
padding: 0.14rem 0.32rem;
|
||||
border-radius: 0.55rem;
|
||||
border: 1px solid transparent;
|
||||
transition:
|
||||
color 0.18s ease,
|
||||
background-color 0.18s ease,
|
||||
border-color 0.18s ease,
|
||||
transform 0.18s ease;
|
||||
}
|
||||
|
||||
div#contents-big a:visited {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
div#contents-big a:hover {
|
||||
background-color: var(--color-linkhbg);
|
||||
color: var(--color-linkh);
|
||||
}
|
||||
|
||||
div#contents-big li > a:hover,
|
||||
div#contents-big li > a:focus-visible {
|
||||
border-color: var(--color-border);
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
div#contents-big li > a:focus-visible,
|
||||
div#contents-big .mini-header a:focus-visible {
|
||||
outline: 2px solid var(--color-link);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
div#contents-big .mini-header a {
|
||||
display: inline;
|
||||
margin-left: 0.25rem;
|
||||
color: var(--color-link);
|
||||
font-size: 0.85rem;
|
||||
line-height: 1;
|
||||
vertical-align: baseline;
|
||||
transition: color 0.18s ease;
|
||||
}
|
||||
|
||||
div#contents-big .mini-header a:hover {
|
||||
background-color: transparent;
|
||||
color: var(--color-linkh);
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.text-space {
|
||||
@@ -733,7 +457,6 @@ hr {
|
||||
max-width: 875px;
|
||||
}
|
||||
}
|
||||
|
||||
/* sidebar+sidenotes */
|
||||
@media (min-width: 1200px) {
|
||||
body {
|
||||
@@ -743,6 +466,7 @@ hr {
|
||||
}
|
||||
|
||||
@media print {
|
||||
|
||||
.no-print,
|
||||
.no-print * {
|
||||
display: none !important;
|
||||
@@ -750,16 +474,5 @@ hr {
|
||||
|
||||
body {
|
||||
margin: auto;
|
||||
background: white;
|
||||
}
|
||||
|
||||
blockquote,
|
||||
details,
|
||||
div#contents-big,
|
||||
figure,
|
||||
pre,
|
||||
div.highlight,
|
||||
table {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,79 +1,35 @@
|
||||
:root {
|
||||
--syntax-alert: #c2410c;
|
||||
--syntax-annotation: #0f766e;
|
||||
--syntax-attribute: #2563eb;
|
||||
--syntax-number: #7c3aed;
|
||||
--syntax-control: #4d7c0f;
|
||||
--syntax-char: #0f766e;
|
||||
--syntax-constant: #9f1239;
|
||||
--syntax-comment: #7b8794;
|
||||
--syntax-doc: #b45309;
|
||||
--syntax-type-bg: #efe7ff;
|
||||
--syntax-error: #dc2626;
|
||||
--syntax-function: #0f4c81;
|
||||
--syntax-import: #0d9488;
|
||||
--syntax-preprocessor: #92400e;
|
||||
--syntax-special: #0369a1;
|
||||
--syntax-string: #15803d;
|
||||
--syntax-variable: #1d4ed8;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--syntax-alert: #fdba74;
|
||||
--syntax-annotation: #99f6e4;
|
||||
--syntax-attribute: #93c5fd;
|
||||
--syntax-number: #d8b4fe;
|
||||
--syntax-control: #bef264;
|
||||
--syntax-char: #86efac;
|
||||
--syntax-constant: #fda4af;
|
||||
--syntax-comment: #94a3b8;
|
||||
--syntax-doc: #fcd34d;
|
||||
--syntax-type-bg: rgba(216, 180, 254, 0.16);
|
||||
--syntax-error: #f87171;
|
||||
--syntax-function: #bfdbfe;
|
||||
--syntax-import: #5eead4;
|
||||
--syntax-preprocessor: #fdba74;
|
||||
--syntax-special: #7dd3fc;
|
||||
--syntax-string: #86efac;
|
||||
--syntax-variable: #c4b5fd;
|
||||
code.sourceCode
|
||||
{
|
||||
background: inherit
|
||||
}
|
||||
}
|
||||
|
||||
code.sourceCode {
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
pre > code.sourceCode > span > a:first-child::before {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
code span.al { color: var(--syntax-alert); font-weight: 700; }
|
||||
code span.an { color: var(--syntax-annotation); font-weight: 700; font-style: italic; }
|
||||
code span.at { color: var(--syntax-attribute); }
|
||||
code span.bn { color: var(--syntax-number); }
|
||||
code span.bu { color: var(--syntax-function); }
|
||||
code span.cf { color: var(--syntax-control); font-weight: 700; }
|
||||
code span.ch { color: var(--syntax-char); }
|
||||
code span.cn { color: var(--syntax-constant); }
|
||||
code span.co { color: var(--syntax-comment); font-style: italic; }
|
||||
code span.cv { color: var(--syntax-annotation); font-weight: 700; font-style: italic; }
|
||||
code span.do { color: var(--syntax-doc); font-style: italic; }
|
||||
code span.dt { background-color: var(--syntax-type-bg); }
|
||||
code span.dv { color: var(--syntax-number); }
|
||||
code span.er { color: var(--syntax-error); font-weight: 700; }
|
||||
code span.ex { color: var(--syntax-function); }
|
||||
code span.fl { color: var(--syntax-number); }
|
||||
code span.fu { color: var(--syntax-function); }
|
||||
code span.im { color: var(--syntax-import); }
|
||||
code span.in { color: var(--syntax-annotation); font-weight: 700; font-style: italic; }
|
||||
code span.kw { color: var(--syntax-control); font-weight: 700; }
|
||||
code span.op { color: var(--syntax-function); font-weight: 700; }
|
||||
code span.ot { color: var(--syntax-special); font-weight: 700; }
|
||||
code span.pp { color: var(--syntax-preprocessor); }
|
||||
code span.sc { color: var(--syntax-special); }
|
||||
code span.ss { color: var(--syntax-number); }
|
||||
code span.st { color: var(--syntax-string); }
|
||||
code span.va { color: var(--syntax-variable); }
|
||||
code span.vs { color: var(--syntax-special); }
|
||||
code span.wa { color: var(--syntax-annotation); font-weight: 700; font-style: italic; }
|
||||
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 */
|
||||
@@ -19,148 +19,127 @@ body {
|
||||
.sidenote,
|
||||
.marginnote,
|
||||
.marginnote-left {
|
||||
position: relative;
|
||||
float: right;
|
||||
clear: right;
|
||||
width: 36%;
|
||||
margin-top: 0.45rem;
|
||||
margin-right: -42%;
|
||||
width: 36%;
|
||||
margin-top: 0.3rem;
|
||||
margin-bottom: 0;
|
||||
padding: 0.85rem 1rem;
|
||||
background-color: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 1rem;
|
||||
box-shadow: var(--color-shadow-soft);
|
||||
backdrop-filter: blur(14px);
|
||||
font-size: 0.8em;
|
||||
line-height: 1.2;
|
||||
vertical-align: baseline;
|
||||
font-size: 0.82em;
|
||||
line-height: 1.45;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.sidenote,
|
||||
.marginnote,
|
||||
.marginnote-left {
|
||||
width: 33%;
|
||||
margin-right: -40%;
|
||||
width: 33%;
|
||||
}
|
||||
}
|
||||
|
||||
.marginnote-left {
|
||||
position: relative;
|
||||
float: left;
|
||||
clear: left;
|
||||
width: 25%;
|
||||
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. */
|
||||
@media (max-width: 1349px), (min-width: 1367px) and (max-width: 1620px) {
|
||||
/* 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 {
|
||||
width: 30%;
|
||||
margin-left: -33%;
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
|
||||
.sidenote > :first-child,
|
||||
.marginnote > :first-child,
|
||||
.marginnote-left > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.sidenote > :last-child,
|
||||
.marginnote > :last-child,
|
||||
.marginnote-left > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.sidenote code {
|
||||
font-size: 0.92em;
|
||||
font-size: 0.94em;
|
||||
}
|
||||
|
||||
/* Block code in side and margin notes gets a vertical scrollbar on some
|
||||
browsers; disable that. */
|
||||
/* 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 {
|
||||
margin: 0.75rem 0;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.sidenote-number {
|
||||
color: var(--color-link);
|
||||
counter-increment: sidenote-counter;
|
||||
font-family: "IosevkaC", sans-serif;
|
||||
color: var(--color-link);
|
||||
}
|
||||
|
||||
.sidenote-number:after,
|
||||
.sidenote:before {
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
color: var(--color-link);
|
||||
font-family: "IosevkaC", sans-serif;
|
||||
}
|
||||
|
||||
.sidenote-number:after {
|
||||
content: counter(sidenote-counter);
|
||||
top: -0.5rem;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
top: -0.5rem;
|
||||
}
|
||||
|
||||
/* Properly position sidenote number and adjust position of sidenote
|
||||
/* 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) " ";
|
||||
position: absolute;
|
||||
top: -0.55rem;
|
||||
right: calc(100% + 0.5em);
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
top: -0.55rem;
|
||||
position: absolute;
|
||||
right: calc(100% + 0.5em);
|
||||
}
|
||||
|
||||
.sidenote p {
|
||||
margin: 0.85em 0;
|
||||
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;
|
||||
max-height: 2rem; /* should be less than or equal to paragraph line-height */
|
||||
}
|
||||
|
||||
label.margin-toggle:not(.sidenote-number) {
|
||||
display: none;
|
||||
color: var(--color-link);
|
||||
font-family: "IosevkaC", sans-serif;
|
||||
}
|
||||
|
||||
.iframe-wrapper {
|
||||
position: relative;
|
||||
height: 0;
|
||||
padding-bottom: 56.25%; /* 16:9 */
|
||||
padding-top: 25px;
|
||||
padding-bottom: 56.25%;
|
||||
overflow: hidden;
|
||||
background-color: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 1rem;
|
||||
box-shadow: var(--color-shadow-soft);
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.iframe-wrapper iframe {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
@@ -174,24 +153,23 @@ label.margin-toggle:not(.sidenote-number) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Linkify sidenotes iff they are clickable. */
|
||||
/* Linkify sidenotes iff they are clickable */
|
||||
.margin-toggle,
|
||||
.sidenote-number:after {
|
||||
color: var(--color-link);
|
||||
text-decoration: underline;
|
||||
text-decoration-color: var(--color-link-line);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.margin-toggle:checked + .sidenote,
|
||||
.margin-toggle:checked + .marginnote,
|
||||
.margin-toggle:checked + .marginnote-left {
|
||||
position: relative;
|
||||
display: block;
|
||||
float: left;
|
||||
left: 1rem;
|
||||
clear: both;
|
||||
display: block;
|
||||
width: 95%;
|
||||
margin: 1rem 2.5%;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
name: hakyll-blog
|
||||
name: hakysidian
|
||||
version: 0.1.0.0
|
||||
build-type: Simple
|
||||
cabal-version: >= 1.10
|
||||
cabal-version: 2.0
|
||||
data-files:
|
||||
templates/*.html
|
||||
css/*.css
|
||||
fonts/*.woff2
|
||||
bib_style.csl
|
||||
favicon.ico
|
||||
|
||||
|
||||
executable site
|
||||
hs-source-dirs: src
|
||||
main-is: site.hs
|
||||
other-modules: ChaoDoc, SideNoteHTML, Pangu
|
||||
autogen-modules: Paths_hakysidian
|
||||
other-modules: ChaoDoc, SideNoteHTML, Pangu, Paths_hakysidian
|
||||
build-depends: base >= 4.18
|
||||
, hakyll >= 4.15
|
||||
, mtl >= 2.2.2
|
||||
@@ -17,10 +24,12 @@ executable site
|
||||
, tagsoup
|
||||
, text
|
||||
, containers
|
||||
, directory
|
||||
-- , process
|
||||
-- , regex-compat
|
||||
, array
|
||||
, filepath
|
||||
, temporary
|
||||
-- , ghc-syntax-highlighter
|
||||
-- , blaze-html >= 0.9
|
||||
, megaparsec
|
||||
542
src/site.hs
542
src/site.hs
@@ -2,13 +2,32 @@
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE ScopedTypeVariables #-}
|
||||
{-# LANGUAGE StandaloneKindSignatures #-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
|
||||
import ChaoDoc
|
||||
import Data.List (sortOn)
|
||||
import Control.Monad (filterM, forM_, unless)
|
||||
import Data.Kind (Type)
|
||||
import Data.List (sortOn, stripPrefix)
|
||||
import qualified Data.Text as T
|
||||
import Hakyll
|
||||
import qualified Paths_hakysidian as Paths
|
||||
import System.Directory
|
||||
( copyFile,
|
||||
createDirectoryIfMissing,
|
||||
createDirectoryLink,
|
||||
createFileLink,
|
||||
doesDirectoryExist,
|
||||
doesFileExist,
|
||||
listDirectory,
|
||||
makeAbsolute,
|
||||
withCurrentDirectory
|
||||
)
|
||||
import System.Environment (getArgs, withArgs)
|
||||
import System.Exit (die, exitSuccess)
|
||||
import System.FilePath
|
||||
import System.IO.Error (tryIOError)
|
||||
import System.IO.Temp (withSystemTempDirectory)
|
||||
import Text.Pandoc
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -16,35 +35,371 @@ import Text.Pandoc
|
||||
cleanRoute :: Routes
|
||||
cleanRoute = customRoute createIndexRoute
|
||||
where
|
||||
createIndexRoute ident = takeDirectory p </> takeBaseName p </> "index.html"
|
||||
createIndexRoute :: Identifier -> FilePath
|
||||
createIndexRoute ident
|
||||
| dir == "." = base </> "index.html"
|
||||
| otherwise = dir </> base </> "index.html"
|
||||
where
|
||||
p = toFilePath ident
|
||||
dir = takeDirectory p
|
||||
base = takeBaseName p
|
||||
|
||||
cleanIndexHtmls :: Item String -> Compiler (Item String)
|
||||
cleanIndexHtmls = return . fmap (replaceAll pattern replacement)
|
||||
where
|
||||
pattern :: String = "/index.html"
|
||||
replacement :: String -> String = const "/"
|
||||
pattern :: String
|
||||
pattern = "/index.html"
|
||||
|
||||
replacement :: String -> String
|
||||
replacement = const "/"
|
||||
|
||||
notePattern :: Pattern
|
||||
notePattern =
|
||||
fromGlob "*.md"
|
||||
.&&. complement (fromGlob "math-macros.md")
|
||||
.&&. complement (fromGlob "index.md")
|
||||
|
||||
reservedMarkdownFiles :: [FilePath]
|
||||
reservedMarkdownFiles = ["index.md", "math-macros.md"]
|
||||
|
||||
loadNoteLinks :: Compiler [Item String]
|
||||
loadNoteLinks = do
|
||||
noteIds <- sortOn toFilePath <$> getMatches notePattern
|
||||
pure [Item noteId "" | noteId <- noteIds]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
config :: Configuration
|
||||
config =
|
||||
type CliOptions :: Type
|
||||
data CliOptions = CliOptions
|
||||
{ cliContentDir :: Maybe FilePath,
|
||||
cliOutputDir :: Maybe FilePath,
|
||||
cliReferenceBib :: Maybe FilePath,
|
||||
cliMathMacros :: Maybe FilePath,
|
||||
cliCssDir :: Maybe FilePath,
|
||||
cliFontsDir :: Maybe FilePath,
|
||||
cliTemplatesDir :: Maybe FilePath,
|
||||
cliBibStyle :: Maybe FilePath,
|
||||
cliFavicon :: Maybe FilePath
|
||||
}
|
||||
|
||||
type ResolvedOptions :: Type
|
||||
data ResolvedOptions = ResolvedOptions
|
||||
{ resolvedContentDir :: FilePath,
|
||||
resolvedOutputDir :: FilePath,
|
||||
resolvedStoreDir :: FilePath,
|
||||
resolvedTmpDir :: FilePath,
|
||||
resolvedReferenceBib :: FilePath,
|
||||
resolvedMathMacros :: FilePath,
|
||||
resolvedImagesDir :: Maybe FilePath,
|
||||
resolvedCssDir :: FilePath,
|
||||
resolvedFontsDir :: FilePath,
|
||||
resolvedTemplatesDir :: FilePath,
|
||||
resolvedBibStyle :: FilePath,
|
||||
resolvedFavicon :: FilePath
|
||||
}
|
||||
|
||||
type ParseResult :: Type
|
||||
data ParseResult
|
||||
= Parsed CliOptions [String]
|
||||
| ShowHelp
|
||||
|
||||
defaultCliOptions :: CliOptions
|
||||
defaultCliOptions =
|
||||
CliOptions
|
||||
{ cliContentDir = Nothing,
|
||||
cliOutputDir = Nothing,
|
||||
cliReferenceBib = Nothing,
|
||||
cliMathMacros = Nothing,
|
||||
cliCssDir = Nothing,
|
||||
cliFontsDir = Nothing,
|
||||
cliTemplatesDir = Nothing,
|
||||
cliBibStyle = Nothing,
|
||||
cliFavicon = Nothing
|
||||
}
|
||||
|
||||
helpText :: String
|
||||
helpText =
|
||||
unlines
|
||||
[ "Hakysidian",
|
||||
"",
|
||||
"Usage:",
|
||||
" site [options] [build|watch|clean|rebuild|preview ...]",
|
||||
"",
|
||||
"The content directory should contain top-level markdown files,",
|
||||
"an optional images/ folder, plus reference.bib and math-macros.md.",
|
||||
"",
|
||||
"Options:",
|
||||
" --content-dir PATH Folder containing markdown files.",
|
||||
" --output-dir PATH Destination for generated HTML. Default: CONTENT/_site",
|
||||
" --reference-bib PATH Bibliography file. Default: CONTENT/reference.bib",
|
||||
" --math-macros PATH Math macros file. Default: CONTENT/math-macros.md",
|
||||
" --css-dir PATH Shared CSS directory. Default: packaged asset directory",
|
||||
" --fonts-dir PATH Shared fonts directory. Default: packaged asset directory",
|
||||
" --templates-dir PATH Shared templates directory. Default: packaged asset directory",
|
||||
" --bib-style PATH CSL file. Default: packaged bib_style.csl",
|
||||
" --favicon PATH Favicon file. Default: packaged favicon.ico",
|
||||
" --help Show this help text"
|
||||
]
|
||||
|
||||
parseCliArgs :: [String] -> Either String ParseResult
|
||||
parseCliArgs = go defaultCliOptions []
|
||||
where
|
||||
go :: CliOptions -> [String] -> [String] -> Either String ParseResult
|
||||
go options passthrough = \case
|
||||
[] -> Right (Parsed options (reverse passthrough))
|
||||
"--" : rest -> Right (Parsed options (reverse passthrough ++ rest))
|
||||
"--help" : _ -> Right ShowHelp
|
||||
"-h" : _ -> Right ShowHelp
|
||||
arg : rest
|
||||
| Just value <- stripPrefix "--content-dir=" arg ->
|
||||
go options {cliContentDir = Just value} passthrough rest
|
||||
| Just value <- stripPrefix "--output-dir=" arg ->
|
||||
go options {cliOutputDir = Just value} passthrough rest
|
||||
| Just value <- stripPrefix "--reference-bib=" arg ->
|
||||
go options {cliReferenceBib = Just value} passthrough rest
|
||||
| Just value <- stripPrefix "--ref=" arg ->
|
||||
go options {cliReferenceBib = Just value} passthrough rest
|
||||
| Just value <- stripPrefix "--math-macros=" arg ->
|
||||
go options {cliMathMacros = Just value} passthrough rest
|
||||
| Just value <- stripPrefix "--css-dir=" arg ->
|
||||
go options {cliCssDir = Just value} passthrough rest
|
||||
| Just value <- stripPrefix "--fonts-dir=" arg ->
|
||||
go options {cliFontsDir = Just value} passthrough rest
|
||||
| Just value <- stripPrefix "--templates-dir=" arg ->
|
||||
go options {cliTemplatesDir = Just value} passthrough rest
|
||||
| Just value <- stripPrefix "--bib-style=" arg ->
|
||||
go options {cliBibStyle = Just value} passthrough rest
|
||||
| Just value <- stripPrefix "--favicon=" arg ->
|
||||
go options {cliFavicon = Just value} passthrough rest
|
||||
| arg == "--content-dir" ->
|
||||
setPathOption "--content-dir" cliContentDir (\x y -> x {cliContentDir = Just y}) options passthrough rest
|
||||
| arg == "--output-dir" ->
|
||||
setPathOption "--output-dir" cliOutputDir (\x y -> x {cliOutputDir = Just y}) options passthrough rest
|
||||
| arg == "--reference-bib" ->
|
||||
setPathOption "--reference-bib" cliReferenceBib (\x y -> x {cliReferenceBib = Just y}) options passthrough rest
|
||||
| arg == "--ref" ->
|
||||
setPathOption "--ref" cliReferenceBib (\x y -> x {cliReferenceBib = Just y}) options passthrough rest
|
||||
| arg == "--math-macros" ->
|
||||
setPathOption "--math-macros" cliMathMacros (\x y -> x {cliMathMacros = Just y}) options passthrough rest
|
||||
| arg == "--css-dir" ->
|
||||
setPathOption "--css-dir" cliCssDir (\x y -> x {cliCssDir = Just y}) options passthrough rest
|
||||
| arg == "--fonts-dir" ->
|
||||
setPathOption "--fonts-dir" cliFontsDir (\x y -> x {cliFontsDir = Just y}) options passthrough rest
|
||||
| arg == "--templates-dir" ->
|
||||
setPathOption "--templates-dir" cliTemplatesDir (\x y -> x {cliTemplatesDir = Just y}) options passthrough rest
|
||||
| arg == "--bib-style" ->
|
||||
setPathOption "--bib-style" cliBibStyle (\x y -> x {cliBibStyle = Just y}) options passthrough rest
|
||||
| arg == "--favicon" ->
|
||||
setPathOption "--favicon" cliFavicon (\x y -> x {cliFavicon = Just y}) options passthrough rest
|
||||
| otherwise ->
|
||||
go options (arg : passthrough) rest
|
||||
|
||||
setPathOption ::
|
||||
String ->
|
||||
(CliOptions -> Maybe FilePath) ->
|
||||
(CliOptions -> FilePath -> CliOptions) ->
|
||||
CliOptions ->
|
||||
[String] ->
|
||||
[String] ->
|
||||
Either String ParseResult
|
||||
setPathOption optionName getter setter options passthrough = \case
|
||||
[] -> Left ("Missing value for " ++ optionName)
|
||||
value : rest
|
||||
| null value -> Left ("Missing value for " ++ optionName)
|
||||
| getter options == Nothing ->
|
||||
go (setter options value) passthrough rest
|
||||
| otherwise ->
|
||||
go (setter options value) passthrough rest
|
||||
|
||||
resolveCliOptions :: CliOptions -> IO ResolvedOptions
|
||||
resolveCliOptions options = do
|
||||
contentDir <- makeAbsolute (maybe "." id (cliContentDir options))
|
||||
validateDirectoryExists "content directory" contentDir
|
||||
|
||||
let outputDir0 = maybe (contentDir </> "_site") id (cliOutputDir options)
|
||||
referenceBib0 = maybe (contentDir </> "reference.bib") id (cliReferenceBib options)
|
||||
mathMacros0 = maybe (contentDir </> "math-macros.md") id (cliMathMacros options)
|
||||
storeDir0 = contentDir </> ".hakysidian-cache"
|
||||
tmpDir0 = contentDir </> ".hakysidian-tmp"
|
||||
|
||||
outputDir <- makeAbsolute outputDir0
|
||||
referenceBib <- makeAbsolute referenceBib0
|
||||
mathMacros <- makeAbsolute mathMacros0
|
||||
storeDir <- makeAbsolute storeDir0
|
||||
tmpDir <- makeAbsolute tmpDir0
|
||||
|
||||
validateFileExists "reference bibliography" referenceBib
|
||||
validateFileExists "math macros" mathMacros
|
||||
|
||||
imagesDir <- resolveOptionalDirectory (contentDir </> "images")
|
||||
cssDir <- resolveDirectoryOption "css directory" (cliCssDir options) defaultCssDir
|
||||
fontsDir <- resolveDirectoryOption "fonts directory" (cliFontsDir options) defaultFontsDir
|
||||
templatesDir <- resolveDirectoryOption "templates directory" (cliTemplatesDir options) defaultTemplatesDir
|
||||
bibStyle <- resolveFileOption "CSL file" (cliBibStyle options) defaultBibStyle
|
||||
favicon <- resolveFileOption "favicon" (cliFavicon options) defaultFavicon
|
||||
|
||||
pure
|
||||
ResolvedOptions
|
||||
{ resolvedContentDir = contentDir,
|
||||
resolvedOutputDir = outputDir,
|
||||
resolvedStoreDir = storeDir,
|
||||
resolvedTmpDir = tmpDir,
|
||||
resolvedReferenceBib = referenceBib,
|
||||
resolvedMathMacros = mathMacros,
|
||||
resolvedImagesDir = imagesDir,
|
||||
resolvedCssDir = cssDir,
|
||||
resolvedFontsDir = fontsDir,
|
||||
resolvedTemplatesDir = templatesDir,
|
||||
resolvedBibStyle = bibStyle,
|
||||
resolvedFavicon = favicon
|
||||
}
|
||||
|
||||
defaultCssDir :: IO FilePath
|
||||
defaultCssDir = takeDirectory <$> resolvePackagedFile ("css" </> "default.css")
|
||||
|
||||
defaultFontsDir :: IO FilePath
|
||||
defaultFontsDir = takeDirectory <$> resolvePackagedFile ("fonts" </> "IosevkaCustom-Regular.woff2")
|
||||
|
||||
defaultTemplatesDir :: IO FilePath
|
||||
defaultTemplatesDir = takeDirectory <$> resolvePackagedFile ("templates" </> "head.html")
|
||||
|
||||
defaultBibStyle :: IO FilePath
|
||||
defaultBibStyle = resolvePackagedFile "bib_style.csl"
|
||||
|
||||
defaultFavicon :: IO FilePath
|
||||
defaultFavicon = resolvePackagedFile "favicon.ico"
|
||||
|
||||
resolvePackagedFile :: FilePath -> IO FilePath
|
||||
resolvePackagedFile relativePath = do
|
||||
installedPath <- Paths.getDataFileName relativePath
|
||||
installedExists <- doesFileExist installedPath
|
||||
if installedExists
|
||||
then pure installedPath
|
||||
else makeAbsolute relativePath
|
||||
|
||||
resolveDirectoryOption ::
|
||||
String ->
|
||||
Maybe FilePath ->
|
||||
IO FilePath ->
|
||||
IO FilePath
|
||||
resolveDirectoryOption label maybePath defaultAction = do
|
||||
path0 <- maybe defaultAction pure maybePath
|
||||
path <- makeAbsolute path0
|
||||
validateDirectoryExists label path
|
||||
pure path
|
||||
|
||||
resolveFileOption ::
|
||||
String ->
|
||||
Maybe FilePath ->
|
||||
IO FilePath ->
|
||||
IO FilePath
|
||||
resolveFileOption label maybePath defaultAction = do
|
||||
path0 <- maybe defaultAction pure maybePath
|
||||
path <- makeAbsolute path0
|
||||
validateFileExists label path
|
||||
pure path
|
||||
|
||||
resolveOptionalDirectory :: FilePath -> IO (Maybe FilePath)
|
||||
resolveOptionalDirectory path0 = do
|
||||
path <- makeAbsolute path0
|
||||
exists <- doesDirectoryExist path
|
||||
pure if exists then Just path else Nothing
|
||||
|
||||
validateDirectoryExists :: String -> FilePath -> IO ()
|
||||
validateDirectoryExists label path = do
|
||||
exists <- doesDirectoryExist path
|
||||
unless exists $
|
||||
die ("Missing " ++ label ++ ": " ++ path)
|
||||
|
||||
validateFileExists :: String -> FilePath -> IO ()
|
||||
validateFileExists label path = do
|
||||
exists <- doesFileExist path
|
||||
unless exists $
|
||||
die ("Missing " ++ label ++ ": " ++ path)
|
||||
|
||||
findMarkdownSources :: FilePath -> IO [FilePath]
|
||||
findMarkdownSources contentDir = do
|
||||
entries <- listDirectory contentDir
|
||||
let candidatePaths = sortOn takeFileName (map (contentDir </>) entries)
|
||||
files <- filterM doesFileExist candidatePaths
|
||||
pure
|
||||
[ path
|
||||
| path <- files,
|
||||
let fileName = takeFileName path,
|
||||
takeExtension fileName == ".md",
|
||||
fileName `notElem` reservedMarkdownFiles
|
||||
]
|
||||
|
||||
prepareStageRoot :: ResolvedOptions -> FilePath -> IO ()
|
||||
prepareStageRoot options stageRoot = do
|
||||
createDirectoryIfMissing True stageRoot
|
||||
|
||||
markdownFiles <- findMarkdownSources (resolvedContentDir options)
|
||||
forM_ markdownFiles \path ->
|
||||
linkOrCopyFile path (stageRoot </> takeFileName path)
|
||||
|
||||
forM_ (resolvedImagesDir options) \path ->
|
||||
linkOrCopyDirectory path (stageRoot </> "images")
|
||||
|
||||
linkOrCopyFile (resolvedReferenceBib options) (stageRoot </> "reference.bib")
|
||||
linkOrCopyFile (resolvedMathMacros options) (stageRoot </> "math-macros.md")
|
||||
linkOrCopyDirectory (resolvedCssDir options) (stageRoot </> "css")
|
||||
linkOrCopyDirectory (resolvedFontsDir options) (stageRoot </> "fonts")
|
||||
linkOrCopyDirectory (resolvedTemplatesDir options) (stageRoot </> "templates")
|
||||
linkOrCopyFile (resolvedBibStyle options) (stageRoot </> "bib_style.csl")
|
||||
linkOrCopyFile (resolvedFavicon options) (stageRoot </> "favicon.ico")
|
||||
|
||||
linkOrCopyFile :: FilePath -> FilePath -> IO ()
|
||||
linkOrCopyFile source destination = do
|
||||
createDirectoryIfMissing True (takeDirectory destination)
|
||||
result <- tryIOError (createFileLink source destination)
|
||||
case result of
|
||||
Right () -> pure ()
|
||||
Left _ -> copyFile source destination
|
||||
|
||||
linkOrCopyDirectory :: FilePath -> FilePath -> IO ()
|
||||
linkOrCopyDirectory source destination = do
|
||||
createDirectoryIfMissing True (takeDirectory destination)
|
||||
result <- tryIOError (createDirectoryLink source destination)
|
||||
case result of
|
||||
Right () -> pure ()
|
||||
Left _ -> copyDirectoryRecursive source destination
|
||||
|
||||
copyDirectoryRecursive :: FilePath -> FilePath -> IO ()
|
||||
copyDirectoryRecursive source destination = do
|
||||
createDirectoryIfMissing True destination
|
||||
entries <- listDirectory source
|
||||
forM_ entries \entry -> do
|
||||
let srcPath = source </> entry
|
||||
dstPath = destination </> entry
|
||||
isDirectory <- doesDirectoryExist srcPath
|
||||
if isDirectory
|
||||
then copyDirectoryRecursive srcPath dstPath
|
||||
else copyFile srcPath dstPath
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
config :: ResolvedOptions -> Configuration
|
||||
config options =
|
||||
defaultConfiguration
|
||||
{ ignoreFile = \path ->
|
||||
{ destinationDirectory = resolvedOutputDir options,
|
||||
storeDirectory = resolvedStoreDir options,
|
||||
tmpDirectory = resolvedTmpDir options,
|
||||
providerDirectory = ".",
|
||||
ignoreFile = \path ->
|
||||
ignoreFile defaultConfiguration path
|
||||
|| ".git" `elem` splitDirectories (normalise path)
|
||||
}
|
||||
|
||||
main :: IO ()
|
||||
main = hakyllWith config $ do
|
||||
siteRules :: Rules ()
|
||||
siteRules = do
|
||||
match "images/**" $ do
|
||||
route idRoute
|
||||
compile copyFileCompiler
|
||||
|
||||
match "math-macros.md" $ compile getResourceBody
|
||||
|
||||
match "fonts/*.woff2" $ do
|
||||
match "fonts/**" $ do
|
||||
route idRoute
|
||||
compile copyFileCompiler
|
||||
|
||||
@@ -52,68 +407,26 @@ main = hakyllWith config $ do
|
||||
route idRoute
|
||||
compile copyFileCompiler
|
||||
|
||||
-- match "404.html" $ do
|
||||
-- route cleanRoute
|
||||
-- compile copyFileCompiler
|
||||
|
||||
match "css/*" $ do
|
||||
match "css/**" $ do
|
||||
route idRoute
|
||||
compile compressCssCompiler
|
||||
|
||||
-- match "about.md" $ do
|
||||
-- route cleanRoute
|
||||
-- compile $
|
||||
-- chaoDocCompiler
|
||||
-- >>= loadAndApplyTemplate "templates/about.html" defaultContext
|
||||
-- >>= relativizeUrls
|
||||
|
||||
-- -- build up tags
|
||||
-- tags <- buildTags "posts/*" (fromCapture "tags/*.html")
|
||||
-- tagsRules tags $ \tag pattern -> do
|
||||
-- let title = "Posts tagged \"" ++ tag ++ "\""
|
||||
-- route cleanRoute
|
||||
-- compile $ do
|
||||
-- posts <- recentFirst =<< loadAll pattern
|
||||
-- let ctx =
|
||||
-- constField "title" title
|
||||
-- `mappend` listField "posts" (postCtxWithTags tags) (return posts)
|
||||
-- `mappend` defaultContext
|
||||
-- makeItem ""
|
||||
-- >>= loadAndApplyTemplate "templates/tag.html" ctx
|
||||
-- >>= loadAndApplyTemplate "templates/default.html" ctx
|
||||
-- >>= relativizeUrls
|
||||
|
||||
-- create ["tags.html"] $ do
|
||||
-- route cleanRoute
|
||||
-- compile $ do
|
||||
-- makeItem ""
|
||||
-- >>= loadAndApplyTemplate "templates/tags.html" (defaultCtxWithTags tags)
|
||||
-- >>= loadAndApplyTemplate "templates/default.html" (defaultCtxWithTags tags)
|
||||
|
||||
-- match "posts/*" $ do
|
||||
-- route cleanRoute
|
||||
-- compile $ do
|
||||
-- tocCtx <- getTocCtx (postCtxWithTags tags)
|
||||
-- chaoDocCompiler
|
||||
-- >>= loadAndApplyTemplate "templates/post.html" tocCtx
|
||||
-- >>= loadAndApplyTemplate "templates/default.html" tocCtx
|
||||
-- >>= relativizeUrls
|
||||
-- -- >>= katexFilter
|
||||
|
||||
match "notes/*" $ do
|
||||
match notePattern $ do
|
||||
route cleanRoute
|
||||
compile $ do
|
||||
tocCtx <- getTocCtx defaultContext
|
||||
notes <- loadNoteLinks
|
||||
tocCtx <- getTocCtx $ listField "notes" defaultContext (return notes) <> defaultContext
|
||||
chaoDocCompiler
|
||||
>>= loadAndApplyTemplate "templates/note.html" tocCtx
|
||||
>>= relativizeUrls
|
||||
>>= cleanIndexHtmls
|
||||
|
||||
create ["index.html"] $ do
|
||||
route idRoute
|
||||
compile $ do
|
||||
notes <- sortOn (toFilePath . itemIdentifier) <$> loadAll "notes/*"
|
||||
notes <- loadNoteLinks
|
||||
let notesCtx =
|
||||
listField "posts" defaultContext (return notes)
|
||||
listField "notes" defaultContext (return notes)
|
||||
`mappend` constField "title" "Notes"
|
||||
`mappend` defaultContext
|
||||
makeItem ""
|
||||
@@ -122,103 +435,28 @@ main = hakyllWith config $ do
|
||||
>>= relativizeUrls
|
||||
>>= cleanIndexHtmls
|
||||
|
||||
-- create ["archive.html"] $ do
|
||||
-- route cleanRoute
|
||||
-- compile $ do
|
||||
-- posts <- recentFirst =<< loadAll "posts/*"
|
||||
-- let archiveCtx =
|
||||
-- listField "posts" postCtx (return posts)
|
||||
-- `mappend` constField "title" "Archives"
|
||||
-- `mappend` defaultContext
|
||||
-- makeItem ""
|
||||
-- >>= loadAndApplyTemplate "templates/archive.html" archiveCtx
|
||||
-- >>= loadAndApplyTemplate "templates/index.html" archiveCtx
|
||||
-- >>= relativizeUrls
|
||||
-- >>= cleanIndexHtmls
|
||||
|
||||
-- create ["draft.html"] $ do
|
||||
-- route cleanRoute
|
||||
-- compile $ do
|
||||
-- posts <- recentFirst =<< loadAll "posts/*"
|
||||
-- let draftCtx =
|
||||
-- listField "posts" postCtx (return posts)
|
||||
-- `mappend` constField "title" "Drafts"
|
||||
-- `mappend` defaultContext
|
||||
-- makeItem ""
|
||||
-- >>= loadAndApplyTemplate "templates/draft.html" draftCtx
|
||||
-- >>= loadAndApplyTemplate "templates/index.html" draftCtx
|
||||
-- >>= relativizeUrls
|
||||
-- >>= cleanIndexHtmls
|
||||
|
||||
-- match "index.html" $ do
|
||||
-- route idRoute
|
||||
-- compile $ do
|
||||
-- posts <- fmap (take 25) . recentFirst =<< loadAll "posts/*"
|
||||
-- let indexCtx =
|
||||
-- listField "posts" postCtx (return posts)
|
||||
-- `mappend` defaultContext
|
||||
-- getResourceBody
|
||||
-- >>= applyAsTemplate indexCtx
|
||||
-- >>= loadAndApplyTemplate "templates/index.html" indexCtx
|
||||
-- >>= relativizeUrls
|
||||
-- >>= cleanIndexHtmls
|
||||
|
||||
match "templates/*" $ compile templateBodyCompiler
|
||||
|
||||
-- https://robertwpearce.com/hakyll-pt-2-generating-a-sitemap-xml-file.html
|
||||
-- create ["sitemap.xml"] $ do
|
||||
-- route idRoute
|
||||
-- compile $ do
|
||||
-- posts <- recentFirst =<< loadAll "posts/*"
|
||||
-- singlePages <- loadAll (fromList ["about.md"])
|
||||
-- let pages = posts <> singlePages
|
||||
-- sitemapCtx =
|
||||
-- constField "root" root
|
||||
-- <> listField "pages" postCtx (return pages) -- here
|
||||
-- makeItem ""
|
||||
-- >>= loadAndApplyTemplate "templates/sitemap.xml" sitemapCtx
|
||||
main :: IO ()
|
||||
main = do
|
||||
rawArgs <- getArgs
|
||||
parseResult <-
|
||||
case parseCliArgs rawArgs of
|
||||
Left err -> die err
|
||||
Right result -> pure result
|
||||
case parseResult of
|
||||
ShowHelp -> putStrLn helpText >> exitSuccess
|
||||
Parsed cliOptions hakyllArgs -> do
|
||||
resolved <- resolveCliOptions cliOptions
|
||||
createDirectoryIfMissing True (resolvedStoreDir resolved)
|
||||
createDirectoryIfMissing True (resolvedTmpDir resolved)
|
||||
withSystemTempDirectory "hakysidian-stage" \stageRoot -> do
|
||||
prepareStageRoot resolved stageRoot
|
||||
withCurrentDirectory stageRoot $
|
||||
withArgs hakyllArgs $
|
||||
hakyllWith (config resolved) siteRules
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- isZhField :: Context String
|
||||
-- isZhField = boolFieldM "isZh" isZh
|
||||
-- where
|
||||
-- isZh :: Item String -> Compiler Bool
|
||||
-- isZh item = do
|
||||
-- maybeLang <- getMetadataField (itemIdentifier item) "lang"
|
||||
-- return (maybeLang == Just "zh")
|
||||
|
||||
-- postCtx :: Context String
|
||||
-- postCtx =
|
||||
-- dateField "date" "%B %e, %Y"
|
||||
-- <> dateField "date" "%Y-%m-%d"
|
||||
-- <> isZhField
|
||||
-- <> defaultContext
|
||||
|
||||
-- postCtxWithTags :: Tags -> Context String
|
||||
-- postCtxWithTags tags = tagsField "tags" tags `mappend` postCtx
|
||||
|
||||
-- defaultCtxWithTags :: Tags -> Context String
|
||||
-- defaultCtxWithTags tags = listField "tags" tagsCtx getAllTags <> defaultContext
|
||||
-- where
|
||||
-- getAllTags :: Compiler [Item (String, [Identifier])]
|
||||
-- getAllTags = pure . map mkItem $ tagsMap tags
|
||||
-- where
|
||||
-- mkItem :: (String, [Identifier]) -> Item (String, [Identifier])
|
||||
-- mkItem x@(t, _) = Item (tagsMakeId tags t) x
|
||||
-- tagsCtx =
|
||||
-- listFieldWith "posts" (postCtxWithTags tags) getPosts
|
||||
-- <> metadataField
|
||||
-- <> urlField "url"
|
||||
-- <> pathField "path"
|
||||
-- <> titleField "title"
|
||||
-- <> missingField
|
||||
-- where
|
||||
-- getPosts ::
|
||||
-- Item (String, [Identifier]) ->
|
||||
-- Compiler [Item String]
|
||||
-- getPosts (itemBody -> (_, is)) = mapM load is
|
||||
|
||||
-- toc from https://github.com/slotThe/slotThe.github.io
|
||||
getTocCtx :: Context a -> Compiler (Context a)
|
||||
getTocCtx ctx = do
|
||||
|
||||
@@ -10,12 +10,12 @@ $partial("templates/head.html")$
|
||||
<!-- A table of contents on the left side, but only for screens
|
||||
that are big enough -->
|
||||
<div id="contents-big">
|
||||
<p class="mini-header"> <a href="#">Contents</a></p>
|
||||
<div class="toc-scroll">
|
||||
<p class="mini-header">Notes <a id="up-arrow" href="/">←</a></p>
|
||||
$partial("templates/notes-list.html")$
|
||||
<p class="mini-header">Contents <a id="up-arrow" href="#">↑</a></p>
|
||||
$toc$
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-space">
|
||||
<main role="main">
|
||||
<h1 class="pagetitle">$title$</h1>
|
||||
|
||||
7
templates/notes-list.html
Normal file
7
templates/notes-list.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<ul class="notes-list">
|
||||
$for(notes)$
|
||||
<li>
|
||||
<a href="$url$">$title$</a>
|
||||
</li>
|
||||
$endfor$
|
||||
</ul>
|
||||
@@ -1,8 +1,2 @@
|
||||
<h1 class="pagetitle">$title$</h1>
|
||||
<ul>
|
||||
$for(posts)$
|
||||
<li>
|
||||
<a href="$url$">$title$</a>
|
||||
</li>
|
||||
$endfor$
|
||||
</ul>
|
||||
$partial("templates/notes-list.html")$
|
||||
|
||||
Reference in New Issue
Block a user