diff --git a/css/agda.scss b/css/agda.scss new file mode 100644 index 0000000..03ae77b --- /dev/null +++ b/css/agda.scss @@ -0,0 +1,98 @@ +$code-bg: hsl(230,1%,98%); +$code-fg: #ABB2BF; +$code-red: #D65122; +$code-red-br: #AE3B36; +$code-green: #88B966; +$code-yellow: #DEB468; +$code-orange: #C58853; +$code-blue: #519DEB; +$code-pink: #C678DD; +$code-cyan: #48A8B5; +$code-white: #ABB2BF; +$code-grey: #7F848E; + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 400; + font-stretch: normal; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-regular.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-regular.ttf') format('truetype'); +} + +body { + margin: 0; + background-color:$code-bg; + color:#ABB2BF; +} + +html { + background-color: $code-bg; + color:#ABB2BF; +} + +pre.Agda { + margin: 0; + padding: 1em; + background-color: $code-bg; + color: $code-fg; +} + +@keyframes highlight { + 0% { + background-color: #F5DEB3; + } + 100% { + background-color: $code-bg; + } +} + +/* Aspects. */ +.Agda { + .Comment { color: $code-grey; } + .Background { background-color: $code-bg; } + .Markup { color: $code-fg; } + .Keyword { color: $code-orange; } + .String { color: $code-red; } + .Number { color: $code-pink; } + .Symbol { color: $code-fg; } + .PrimitiveType { color: $code-blue; } + .Pragma { color: $code-fg; } + +/* NameKinds. */ + .Bound { color: $code-fg; } + .Generalizable { color: $code-fg; } + .InductiveConstructor { color: $code-green; } + .CoinductiveConstructor { color: $code-green; } + .Datatype { color: $code-blue; } + .Field { color: #F570B7; } + .Function { color: $code-blue; } + .Module { color: $code-pink; } + .Postulate { color: $code-blue; } + .Primitive { color: $code-blue; } + .Record { color: $code-blue; } + +/* OtherAspects. */ + .UnsolvedMeta { color: $code-fg; background: yellow } + .UnsolvedConstraint { color: $code-fg; background: yellow } + .TerminationProblem { color: $code-fg; background: #FFA07A } + .IncompletePattern { color: $code-fg; background: #F5DEB3 } + .Error { color: red; text-decoration: underline } + .TypeChecks { color: $code-fg; background: #ADD8E6 } + .Deadcode { color: $code-fg; background: #808080 } + .ShadowingInTelescope { color: $code-fg; background: #808080 } + + /* Standard attributes. */ + a { text-decoration: none } + a[href]:hover { + text-decoration: 2px #B4EEB4 underline dotted; + } + a[href]:target { + animation: highlight 2.5s; + } + + background-color: #282C34; + font-family: 'Iosevka', 'Fantasque Sans Mono', 'Roboto Mono', monospace; + font-weight: 400; + font-size: 16pt; +} \ No newline at end of file diff --git a/css/code.css b/css/code.css deleted file mode 100644 index fd2745e..0000000 --- a/css/code.css +++ /dev/null @@ -1,45 +0,0 @@ -code, div.sourceCode { - font-family: Fantasque Sans Mono, Fira Mono, monospace; - font-size: 15pt; -} - -code.inline { - background-color: rgb(250,250,250); - /* border: 1px solid rgb(200,200,200); */ -} - -table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode { - margin: 0; padding: 0; vertical-align: baseline; border: none; -} - -table.sourceCode { - width: 100%; line-height: 100%; -} - -td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; } -td.sourceCode { padding-left: 5px; } -code.kw, span.kw { color: #af005f; } /* Keyword */ -code.dt, span.dt { color: #5f5faf; } /* DataType */ -code.dv, span.dv { color: #268bd2; } /* DecVal */ -code.bn, span.bn { color: #268bd2; } /* BaseN */ -code.fl, span.fl { color: #268bd2; } /* Float */ -code.ch, span.ch { color: #cb4b16; } /* Char */ -code.st, span.st { color: #cb4b16; } /* String */ -code.co, span.co { color: #8a8a8a; } /* Comment */ -code.ot, span.ot { color: #007020; } /* Other */ -code.al, span.al { color: #ff0000; } /* Alert */ -code.fu, span.fu { color: #666666; } /* Function */ -code.er, span.er { color: #ff0000; } /* Error */ -code.wa, span.wa { color: #60a0b0; } /* Warning */ -code.cn, span.cn { color: #880000; } /* Constant */ -code.sc, span.sc { color: #4070a0; } /* SpecialChar */ -code.vs, span.vs { color: #4070a0; } /* VerbatimString */ -code.ss, span.ss { color: #2aa198; } /* SpecialString */ -code.va, span.va { color: #073642; } /* Variable */ -code.cf, span.cf { color: #007020; } /* ControlFlow */ -code.op, span.op { color: #d33682; } /* Operator */ -code.pp, span.pp { color: #bc7a00; } /* Preprocessor */ -code.at, span.at { color: #7d9029; } /* Attribute */ -code.do, span.do { color: #ba2121; } /* Documentation */ -code.an, span.an { color: #60a0b0; } /* Annotation */ -code.cv, span.cv { color: #60a0b0; } /* CommentVar */ diff --git a/css/computermodern.css b/css/computermodern.css deleted file mode 100644 index d33f496..0000000 --- a/css/computermodern.css +++ /dev/null @@ -1,13 +0,0 @@ -@font-face { - font-family: "Computer Modern"; - src: url('/static/cmunorm.woff'); -} - -.math { - font-family: Computer Modern, serif; -} - -.math .display { - font-size: 18px; - text-align: center; -} diff --git a/css/default.scss b/css/default.scss index 93716a9..7d71f6c 100644 --- a/css/default.scss +++ b/css/default.scss @@ -1,50 +1,4 @@ -$purple-50: #faf5ff; -$purple-100: #f3e8ff; -$purple-200: #e9d5ff; -$purple-300: #d8b4fe; -$purple-400: #c084fc; -$purple-500: #a855f7; -$purple-600: #9333ea; -$purple-700: #7e22ce; -$purple-800: #6b21a8; -$purple-900: #581c87; - -$yellow-50: #fefce8; -$yellow-100: #fef9c3; -$yellow-200: #fef08a; -$yellow-300: #fde047; -$yellow-400: #facc15; -$yellow-500: #eab308; -$yellow-600: #ca8a04; -$yellow-700: #a16207; -$yellow-800: #854d0e; -$yellow-900: #713f12; - -$bluegray-50: #f8fafc; -$bluegray-100: #f1f5f9; -$bluegray-200: #e2e8f0; -$bluegray-300: #cbd5e1; -$bluegray-400: #94a3b8; -$bluegray-500: #64748b; -$bluegray-600: #475569; -$bluegray-700: #334155; -$bluegray-800: #1e293b; -$bluegray-900: #0f172a; - -$red-50: #fef2f2; -$red-100: #fee2e2; -$red-200: #fecaca; -$red-300: #fca5a5; -$red-400: #f87171; -$red-500: #ef4444; -$red-600: #dc2626; -$red-700: #b91c1c; -$red-800: #991b1b; -$red-900: #7f1d1d; - -$nav-height: 48px; - -$font-size: 14pt; +@import "vars.scss"; @mixin center-that-bitch { display: flex; @@ -76,7 +30,7 @@ body { overflow-x: clip; } -header { +body > header { background-color: $purple-600; display: flex; height: $nav-height; @@ -132,15 +86,14 @@ header { } @mixin material { - padding-left: 1em; - padding-top: 0.2em; - padding-bottom: 0.2em; + padding: 1em; margin-top: 1em; margin-bottom: 1em; - padding-right: 1em; box-shadow: 2px 2px 6px black; + + border-radius: 10px; } main { @@ -154,6 +107,10 @@ main { box-sizing: border-box; + div#title h2 { + display: none; + } + div#post-toc-container { aside#toc { display: none; @@ -164,6 +121,7 @@ main { width: 100%; line-height: 1.5; } + } div#post-info { @@ -205,6 +163,18 @@ figure { } } +ol, ul { + padding-left: 1.2em; + li { + margin-top: 5px; + margin-bottom: 5px; + p { + margin-top: 5px; + margin-bottom: 5px; + } + } +} + .katex-display { > span.katex { white-space: normal; @@ -226,72 +196,64 @@ div.mathpar { } } -.sourceCode { - font-size: $font-size; -} - -div.sourceCode { - background-color: $yellow-50; +div.columns { + blockquote, details.blockquote { + padding-right: 1em; + padding-left: 1em; + padding-top: 0.2em; + padding-bottom: 0.2em; - @include material; + border: 0; + } +} - flex-grow: 0; - height: auto; +code, pre, .sourceCode { + font-size: $font-size * 1.2; + font-family: 'Iosevka', 'Fantasque Sans Mono', Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; + font-weight: 500; } -div.code-container { - padding: 0; - display: flex; - flex-direction: column; +div.sourceCode, pre { + background-color: $code-bg; + color: $code-fg; + flex-grow: 0; - box-shadow: 2px 2px 6px black; + @include material; - > div.sourceCode, > pre { - background-color: $yellow-50; + overflow-x: auto; + line-height: 1.2; + + code { + display: block; + } - border: 0; - box-shadow: none; - padding: 2em; - padding-bottom: 0.5em; - padding-top: 0.5em; + > pre { + padding: unset; + margin-top: unset; + margin-bottom: unset; + box-shadow: unset; margin: 0; - pre { - margin-top: 5px; - margin-bottom: 5px; - } - - overflow-x: auto; - } - - // this is fucking criminal lmao - div.empty-code-tag { - background-color: $yellow-50; + overflow-y: clip; } +} - div.code-tag { - display: flex; - flex-direction: row-reverse; - height: 1.4em; - - background-color: $yellow-300; - padding: 0.2em; - - span { - @include center-that-bitch; - margin-right: 0.4em; - } - } +p > code { + white-space: nowrap; } -blockquote { - @include left-bordered-block($bluegray-700); +blockquote, details.blockquote { + @include material; - background-color: $bluegray-100; + background-color: $purple-100; - padding-left: 2.5em; margin-left: 0; + margin-right: 0; + + h2 { + margin-top: 0; + } } table { @@ -310,14 +272,14 @@ ul#post-list { list-style-type: none; display: flex; flex-direction: column; - gap: 2em; .post-list-item { @include left-bordered-block($yellow-500); + @include material; - background-color: $yellow-50; + margin: 0; - padding: 1em; + background-color: $yellow-50; .post-list-header { margin-top: 0.2em; @@ -352,7 +314,6 @@ div.contact-list { max-width: 33%; flex-grow: 1; - p { margin: 0; } @@ -378,7 +339,7 @@ div.contact-list { } @media only screen and (max-width: 450px) { - header { + body > header { div#logo { width: 100%; display: flex; @@ -392,32 +353,66 @@ div.contact-list { } @media only screen and (min-width: 1500px) { + .narrow-only { + display: none !important; + } + main { max-width: 100%; - > h1 { - font-size: 26pt; + > div#title { + font-size: 15pt; + h1, h2 { + margin: 0; + } + + h2 { + font-style: italic; + font-weight: normal; + display: block; + z-index: 1; + } + + margin-top: 0.5em; + margin-bottom: 1em; @include center-that-bitch; } div#post-toc-container { display: grid; grid-template-columns: 0.5fr 2fr 0.5fr; + gap: 1em; aside#toc { display: block !important; - max-width: 200px; h3 { @include center-that-bitch; } - ul { - border-left: 2px solid $bluegray-400; - list-style-type: none; - padding-left: 1em; + div#toc-container { + overflow-x: hidden; + width: 100%; + position: sticky; + top: 2em; + + overflow-y: auto; + max-height: 90vh; + + bottom: 2em; + + ul { + border-left: 2px solid $bluegray-400; + list-style-type: none; + padding-left: 1em; + + a { + text-decoration: none; + } - a { - text-decoration: none; + a:hover { + text-decoration: underline; + } } } + } article { @@ -426,10 +421,104 @@ div.contact-list { margin: auto; } } + + div.columns { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1em; + + } + } +} + +#index { + padding-top: 4em; + + a.ico-left { + img { + clip-path: url(#squircle); + width: 96px; + height: 96px; + } + float: left; + margin-right: 1em; + width: 96px; + height: 96px; + } + + a.ico-right { + img { + clip-path: url(#squircle); + width: 96px; + height: 96px; + } + float: right; + margin-left: 1em; + width: 96px; + height: 96px; + } + + div#social { + display: flex; + flex-direction: row; + justify-content: center; + width: 100%; + gap: 8px; + + img { + width: 48px; + height: 48px; + clip-path: url(#squircle); + transition: width 0.25s, height 0.25s; + &:hover { + width: 54px; + height: 54px; + } + } + + a { + filter: drop-shadow(2px 2px 3px rgba(50, 50, 0, 0.5)); + height: 54px; + } } } +@media only screen and (min-width: 1500px) { + #index { + display: grid; + grid-template-columns: 0.20fr 0.75fr 0.20fr 1fr 0.20fr; + } +} + + details { margin-top: 1em; margin-bottom: 1em; -} \ No newline at end of file +} + +// Styles for code +code.kw, span.kw { color: $code-pink; } /* Keyword */ +code.dt, span.dt { color: $code-blue; } /* DataType */ +code.dv, span.dv { color: $code-orange; } /* DecVal */ +code.bn, span.bn { color: $code-orange; } /* BaseN */ +code.fl, span.fl { color: $code-orange; } /* Float */ +code.ch, span.ch { color: $code-green; } /* Char */ +code.st, span.st { color: $code-green; } /* String */ +code.co, span.co { color: $code-grey; } /* Comment */ +code.ot, span.ot { color: $code-green; } /* Other */ +code.al, span.al { color: #ff0000; } /* Alert */ +code.fu, span.fu { color: $code-fg; } /* Function */ +code.er, span.er { color: #ff0000; } /* Error */ +code.wa, span.wa { color: #60a0b0; } /* Warning */ +code.cn, span.cn { color: $code-orange; } /* Constant */ +code.sc, span.sc { color: $code-yellow; } /* SpecialChar */ +code.vs, span.vs { color: $code-blue; } /* VerbatimString */ +code.ss, span.ss { color: $code-green; } /* SpecialString */ +code.va, span.va { color: $code-fg; } /* Variable */ +code.cf, span.cf { color: $code-pink; } /* ControlFlow */ +code.op, span.op { color: $code-green; } /* Operator */ +code.pp, span.pp { color: $code-orange; } /* Preprocessor */ +code.at, span.at { color: $code-green; } /* Attribute */ +code.do, span.do { color: $code-red; } /* Documentation */ +code.an, span.an { color: $code-red; } /* Annotation */ +code.cv, span.cv { color: $code-red; } /* CommentVar */ \ No newline at end of file diff --git a/css/fonts.scss b/css/fonts.scss new file mode 100644 index 0000000..14a3390 --- /dev/null +++ b/css/fonts.scss @@ -0,0 +1,419 @@ +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 400; + font-stretch: normal; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-regular.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-regular.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 400; + font-stretch: expanded; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-extended.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extended.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 400; + font-stretch: normal; + font-style: oblique; + src: url('/static/woff2/iosevk-abbie-oblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-oblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka Oblique'; + font-display: swap; + font-weight: 400; + font-stretch: normal; + src: url('/static/woff2/iosevk-abbie-oblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-oblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 400; + font-stretch: expanded; + font-style: oblique; + src: url('/static/woff2/iosevk-abbie-extendedoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka Oblique'; + font-display: swap; + font-weight: 400; + font-stretch: expanded; + src: url('/static/woff2/iosevk-abbie-extendedoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 400; + font-stretch: normal; + font-style: italic; + src: url('/static/woff2/iosevk-abbie-italic.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-italic.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 400; + font-stretch: expanded; + font-style: italic; + src: url('/static/woff2/iosevk-abbie-extendeditalic.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendeditalic.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 500; + font-stretch: normal; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-medium.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-medium.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 500; + font-stretch: expanded; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-extendedmedium.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedmedium.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 500; + font-stretch: normal; + font-style: oblique; + src: url('/static/woff2/iosevk-abbie-mediumoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-mediumoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka Oblique'; + font-display: swap; + font-weight: 500; + font-stretch: normal; + src: url('/static/woff2/iosevk-abbie-mediumoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-mediumoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 500; + font-stretch: expanded; + font-style: oblique; + src: url('/static/woff2/iosevk-abbie-extendedmediumoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedmediumoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka Oblique'; + font-display: swap; + font-weight: 500; + font-stretch: expanded; + src: url('/static/woff2/iosevk-abbie-extendedmediumoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedmediumoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 500; + font-stretch: normal; + font-style: italic; + src: url('/static/woff2/iosevk-abbie-mediumitalic.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-mediumitalic.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 500; + font-stretch: expanded; + font-style: italic; + src: url('/static/woff2/iosevk-abbie-extendedmediumitalic.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedmediumitalic.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 600; + font-stretch: normal; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-semibold.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-semibold.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 600; + font-stretch: expanded; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-extendedsemibold.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedsemibold.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 600; + font-stretch: normal; + font-style: oblique; + src: url('/static/woff2/iosevk-abbie-semiboldoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-semiboldoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka Oblique'; + font-display: swap; + font-weight: 600; + font-stretch: normal; + src: url('/static/woff2/iosevk-abbie-semiboldoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-semiboldoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 600; + font-stretch: expanded; + font-style: oblique; + src: url('/static/woff2/iosevk-abbie-extendedsemiboldoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedsemiboldoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka Oblique'; + font-display: swap; + font-weight: 600; + font-stretch: expanded; + src: url('/static/woff2/iosevk-abbie-extendedsemiboldoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedsemiboldoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 600; + font-stretch: normal; + font-style: italic; + src: url('/static/woff2/iosevk-abbie-semibolditalic.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-semibolditalic.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 600; + font-stretch: expanded; + font-style: italic; + src: url('/static/woff2/iosevk-abbie-extendedsemibolditalic.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedsemibolditalic.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 700; + font-stretch: normal; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-bold.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-bold.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 700; + font-stretch: expanded; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-extendedbold.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedbold.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 700; + font-stretch: normal; + font-style: oblique; + src: url('/static/woff2/iosevk-abbie-boldoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-boldoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka Oblique'; + font-display: swap; + font-weight: 700; + font-stretch: normal; + src: url('/static/woff2/iosevk-abbie-boldoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-boldoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 700; + font-stretch: expanded; + font-style: oblique; + src: url('/static/woff2/iosevk-abbie-extendedboldoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedboldoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka Oblique'; + font-display: swap; + font-weight: 700; + font-stretch: expanded; + src: url('/static/woff2/iosevk-abbie-extendedboldoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedboldoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 700; + font-stretch: normal; + font-style: italic; + src: url('/static/woff2/iosevk-abbie-bolditalic.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-bolditalic.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 700; + font-stretch: expanded; + font-style: italic; + src: url('/static/woff2/iosevk-abbie-extendedbolditalic.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedbolditalic.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 800; + font-stretch: normal; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-extrabold.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extrabold.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 800; + font-stretch: expanded; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-extendedextrabold.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedextrabold.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 800; + font-stretch: normal; + font-style: oblique; + src: url('/static/woff2/iosevk-abbie-extraboldoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extraboldoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka Oblique'; + font-display: swap; + font-weight: 800; + font-stretch: normal; + src: url('/static/woff2/iosevk-abbie-extraboldoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extraboldoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 800; + font-stretch: expanded; + font-style: oblique; + src: url('/static/woff2/iosevk-abbie-extendedextraboldoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedextraboldoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka Oblique'; + font-display: swap; + font-weight: 800; + font-stretch: expanded; + src: url('/static/woff2/iosevk-abbie-extendedextraboldoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedextraboldoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 800; + font-stretch: normal; + font-style: italic; + src: url('/static/woff2/iosevk-abbie-extrabolditalic.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extrabolditalic.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 800; + font-stretch: expanded; + font-style: italic; + src: url('/static/woff2/iosevk-abbie-extendedextrabolditalic.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedextrabolditalic.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 900; + font-stretch: normal; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-heavy.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-heavy.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 900; + font-stretch: expanded; + font-style: normal; + src: url('/static/woff2/iosevk-abbie-extendedheavy.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedheavy.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 900; + font-stretch: normal; + font-style: oblique; + src: url('/static/woff2/iosevk-abbie-heavyoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-heavyoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka Oblique'; + font-display: swap; + font-weight: 900; + font-stretch: normal; + src: url('/static/woff2/iosevk-abbie-heavyoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-heavyoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 900; + font-stretch: expanded; + font-style: oblique; + src: url('/static/woff2/iosevk-abbie-extendedheavyoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedheavyoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka Oblique'; + font-display: swap; + font-weight: 900; + font-stretch: expanded; + src: url('/static/woff2/iosevk-abbie-extendedheavyoblique.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedheavyoblique.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 900; + font-stretch: normal; + font-style: italic; + src: url('/static/woff2/iosevk-abbie-heavyitalic.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-heavyitalic.ttf') format('truetype'); +} + +@font-face { + font-family: 'Iosevka'; + font-display: swap; + font-weight: 900; + font-stretch: expanded; + font-style: italic; + src: url('/static/woff2/iosevk-abbie-extendedheavyitalic.woff2') format('woff2'), url('/static/ttf/iosevk-abbie-extendedheavyitalic.ttf') format('truetype'); +} diff --git a/css/vars.scss b/css/vars.scss new file mode 100644 index 0000000..013b3b7 --- /dev/null +++ b/css/vars.scss @@ -0,0 +1,62 @@ +$purple-50: #faf5ff; +$purple-100: #f3e8ff; +$purple-200: #e9d5ff; +$purple-300: #d8b4fe; +$purple-400: #c084fc; +$purple-500: #a855f7; +$purple-600: #9333ea; +$purple-700: #7e22ce; +$purple-800: #6b21a8; +$purple-900: #581c87; + +$yellow-50: #fefce8; +$yellow-100: #fef9c3; +$yellow-200: #fef08a; +$yellow-300: #fde047; +$yellow-400: #facc15; +$yellow-500: #eab308; +$yellow-600: #ca8a04; +$yellow-700: #a16207; +$yellow-800: #854d0e; +$yellow-900: #713f12; + +$bluegray-50: #f8fafc; +$bluegray-100: #f1f5f9; +$bluegray-200: #e2e8f0; +$bluegray-300: #cbd5e1; +$bluegray-400: #94a3b8; +$bluegray-500: #64748b; +$bluegray-600: #475569; +$bluegray-700: #334155; +$bluegray-800: #1e293b; +$bluegray-900: #0f172a; + +$red-50: #fef2f2; +$red-100: #fee2e2; +$red-200: #fecaca; +$red-300: #fca5a5; +$red-400: #f87171; +$red-500: #ef4444; +$red-600: #dc2626; +$red-700: #b91c1c; +$red-800: #991b1b; +$red-900: #7f1d1d; + +$nav-height: 48px; + +$font-size: 14pt; + +$code-bg: #282C34; +$code-fg: #ABB2BF; +$code-red: #D65122; +$code-red-br: #AE3B36; +$code-green: #88B966; +$code-yellow: #DEB468; +$code-orange: #C58853; +$code-blue: #519DEB; +$code-pink: #C678DD; +$code-cyan: #48A8B5; +$code-white: #ABB2BF; +$code-grey: #7F848E; + +// foo \ No newline at end of file diff --git a/package.json b/package.json index c20f31b..93f4eed 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "blag", "version": "1.0.0", - "description": "[Go here instead](https://abby.how)", + "description": "[Go here instead](https://amelia.how)", "main": "index.js", "dependencies": { "katex": "^0.13.11", @@ -14,7 +14,7 @@ }, "repository": { "type": "git", - "url": "https://git.abby.how/abby/blag.git" + "url": "https://git.amelia.how/amelia/blag.git" }, "author": "", "license": "ISC" diff --git a/pages/contact.md b/pages/contact.md index 6cf3d4a..8d377ba 100644 --- a/pages/contact.md +++ b/pages/contact.md @@ -8,19 +8,10 @@ span#reading-length { display: none; }
-
-
- profile picture - Abbie#4600 -
- - My Discord friend requests are always open. Feel free to add me for questions or comments! -
- profile picture - @plt_abbie + @plt_amy
@@ -30,12 +21,11 @@ span#reading-length { display: none; }
- profile picture - abbie + {ames}
- Message me directly on Libera IRC, or join `##dependent` to talk about types! + I'm active in `##dependent` on [libera.chat](https://libera.chat) to talk about types!
@@ -45,8 +35,7 @@ If you like what I do, here are some ways you can support this blog:
-Ko-fi - +Ko-fi You can send me a one-time donation on Ko-Fi. Just remember not to read the name on the receipt! (Paypal sucks)
diff --git a/pages/index.html b/pages/index.html index 54bdf0d..9ef5692 100644 --- a/pages/index.html +++ b/pages/index.html @@ -2,16 +2,78 @@ title: Home --- -
-
-

- You've reached Abigail's blog, a place where I exposit and reflect on programming languages and type theory. - Here's the posts I've written recently: -

- -

Posts

- $partial("templates/post-list.html")$ - -

…or you can find more in the archives.

-
-
\ No newline at end of file +
+
+

Hi!

+ +

+ +profile picture + +I'm Amélia, a non-binary (they/them) mathematician & programmer. This +blog is where I write about programming languages: their implementation, +their semantics, etc. +

+ +
+ +
+ + + + + + + + + + + + + + + + +
+ +
+

+ +cube + +In addition to this blog, I maintain the 1Lab, a formalised, cross-linked +reference resource for Homotopy Type Theory, done in Cubical Agda. +

+ +
+

+ +amulet + +My most significant project other than this blog and the 1lab is Amulet, a functional programming +language in the ML tradition with support for advanced type-level +programming. +

+ +
+ +
+

Posts

+ +

+Here are the lastest 5 posts from the blog: +

+ +$partial("templates/post-list.html")$ + +

…or you can find more in the archives.

+
+
+ + \ No newline at end of file diff --git a/pages/oss.md b/pages/oss.md index cfae73a..6d3a658 100644 --- a/pages/oss.md +++ b/pages/oss.md @@ -8,7 +8,6 @@ span#reading-length { display: none; } This blog redistributes (parts of) the following free software projects: -* **KaTeX** is a fast JavaScript library for rendering LaTeX on the client. I use it to pre-generate amazing looking mathematics at compile time. **KaTeX is licensed under the terms of the MIT license, with a copy available [here](/static/licenses/LICENSE.KaTeX)**. +* **KaTeX** is a fast JavaScript library for rendering LaTeX on the client. I use it to pre-generate amazing looking mathematics at compile time. **KaTeX is licensed under the terms of the MIT license; A copy is available [here](/static/licenses/LICENSE.KaTeX)**. - -* **Fantasque Sans Mono** is the programming font I've used for the past 3 years, including on this website. **Fantasque Sans Mono is distributed under the terms of the Open Font License (OFL), with a copy available [here](/static/licenses/LICENSE.FantasqueSansMono)**. \ No newline at end of file +* **Iosevka** is a customizable monospace font designed for programmers. It's used in this website for code blocks, and also for any Agda developments I've shared under the amelia.how domain. **Iosevka is distributed under the terms of the SIL Open Font License; A copy is available [here](/static/licenses/LICENSE.Iosevka).** \ No newline at end of file diff --git a/pages/posts/2018-03-14-amulet-safety.md b/pages/posts/2018-03-14-amulet-safety.md index 31c3c1a..f06cab1 100644 --- a/pages/posts/2018-03-14-amulet-safety.md +++ b/pages/posts/2018-03-14-amulet-safety.md @@ -270,7 +270,7 @@ family with its polymorphic, inferred type system. [Theorems for Free]: https://people.mpi-sws.org/~dreyer/tor/papers/wadler.pdf [my last post]: /posts/2018-02-18.html -[an implementation of the ST monad]: https://txt.abby.how/st-monad.ml.html +[an implementation of the ST monad]: https://txt.amelia.how/st-monad.ml.html [an entire compiler]: http://compcert.inria.fr/ [operating system kernel]: https://sel4.systems/ diff --git a/pages/posts/2018-03-27-amulet-gadts.md b/pages/posts/2018-03-27-amulet-gadts.md index c73a59a..a7678e3 100644 --- a/pages/posts/2018-03-27-amulet-gadts.md +++ b/pages/posts/2018-03-27-amulet-gadts.md @@ -244,4 +244,4 @@ error, as you can see [here]. [his thesis]: https://repository.brynmawr.edu/cgi/viewcontent.cgi?article=1074&context=compsci_pubs [two weeks ago]: /posts/2018-03-14.html -[here]: https://i.abby.how/68c4d.png +[here]: https://i.amelia.how/68c4d.png diff --git a/pages/posts/2021-03-07-cubical.md b/pages/posts/2021-03-07-cubical.md index 4624578..1ed0bed 100644 --- a/pages/posts/2021-03-07-cubical.md +++ b/pages/posts/2021-03-07-cubical.md @@ -94,7 +94,7 @@ singContr : {A : Type} {a : A} -> isContr (Singl A a) singContr {A} {a} = ((a, \i -> a), \y i -> (y.2 i, \j -> y.2 (iand i j))) ``` -This proof is written syntactically, in the language of [cubical](https://git.abby.how/abby/cubical). This proof appears on [line 114] of the massive source file which has everything I've tried to prove with this so far. What's a module system? The actual proof file has some preliminaries which would be interesting if you care about how cubical type theory is actually implemented. +This proof is written syntactically, in the language of [cubical](https://git.amelia.how/amelia/cubical). This proof appears on [line 114] of the massive source file which has everything I've tried to prove with this so far. What's a module system? The actual proof file has some preliminaries which would be interesting if you care about how cubical type theory is actually implemented. Another operation on equalities which is very hard in MLTT, but trivial with cubes, is function extensionality. You can see why this would be simple if you consider that a pointwise equality between functions would be an element of $A \to \mathbb{I} \to B$, while an equality between functions themselves is an element of $\mathbb{I} \to A \to B$. By simply swapping the binders, we get the naive function extensionality. @@ -415,7 +415,7 @@ Applying the proof that $\mathrm{true} \not\equiv \mathrm{false}$ we have a cont To say that our universe $\mathscr{U}$ with its infinitely many types is lacking some is... weird, I'll admit. However, it's missing a lot of them! A countably infinite amount, in fact. While we have all inductive types, we only have the zero-dimensional inductive types, and not the higher inductive types! -I've written about these before a bit in the previous post, about induction. In short, while inductive types allow us to define types with points, higher inductive types let us define types with points and paths. Full disclosure, of time of writing, the implementation of HITs in [cubical](https://git.abby.how/abby/cubical) is partial, in that their fibrancy structure is a big `error`. However we can still write some simple proofs involving them. +I've written about these before a bit in the previous post, about induction. In short, while inductive types allow us to define types with points, higher inductive types let us define types with points and paths. Full disclosure, of time of writing, the implementation of HITs in [cubical](https://git.amelia.how/amelia/cubical) is partial, in that their fibrancy structure is a big `error`. However we can still write some simple proofs involving them. ### The Interval @@ -549,7 +549,7 @@ The `push` path constructor is parametrised by an element $a : A$ and an endpoin > - The pushout of $A \leftarrow A \times B \to B$ is the **join** of $A$ and $B$, written $A * B$ > - The pushout of $1 \leftarrow A \xrightarrow{f} B$ is the **cone** or **cofiber** of $f$ -The big file with all the proofs in [cubical](https://git.abby.how/abby/cubical) features a proof that the suspension $\Sigma A$ defined directly as a HIT is the same as the one defined by the pushout of $1 \leftarrow A \to 1$. +The big file with all the proofs in [cubical](https://git.amelia.how/amelia/cubical) features a proof that the suspension $\Sigma A$ defined directly as a HIT is the same as the one defined by the pushout of $1 \leftarrow A \to 1$. ## But Why? @@ -600,8 +600,8 @@ To define $\mathrm{comp}\ (\lambda i. \sum{(x : A(i))} B(i)\ x)\ [\phi \to u]\ p $$\mathrm{comp}\ (\lambda i. \textstyle\sum{(x : A(i))} B(i)\ x)\ [\phi \to u]\ p = (v(i1), y\prime)$$ -[here]: https://git.abby.how/abby/cubical/src/branch/master/intro.tt#L436-L460 +[here]: https://git.amelia.how/amelia/cubical/src/branch/master/intro.tt#L436-L460 -[line 114]: https://git.abby.how/abby/cubical/src/commit/fb87b16429fdd54f7e71b653ffaed115015066cc/intro.tt#L110-L114 -[line 667]: https://git.abby.how/abby/cubical/src/commit/fb87b16429fdd54f7e71b653ffaed115015066cc/intro.tt#L667 -[line 675]: https://git.abby.how/abby/cubical/src/commit/fb87b16429fdd54f7e71b653ffaed115015066cc/intro.tt#L675 \ No newline at end of file +[line 114]: https://git.amelia.how/amelia/cubical/src/commit/fb87b16429fdd54f7e71b653ffaed115015066cc/intro.tt#L110-L114 +[line 667]: https://git.amelia.how/amelia/cubical/src/commit/fb87b16429fdd54f7e71b653ffaed115015066cc/intro.tt#L667 +[line 675]: https://git.amelia.how/amelia/cubical/src/commit/fb87b16429fdd54f7e71b653ffaed115015066cc/intro.tt#L675 \ No newline at end of file diff --git a/pages/posts/2021-06-07-ax-j.md b/pages/posts/2021-06-07-ax-j.md index 725d449..72d6730 100644 --- a/pages/posts/2021-06-07-ax-j.md +++ b/pages/posts/2021-06-07-ax-j.md @@ -1,7 +1,7 @@ --- title: "A quickie: Axiom J" date: June 7th, 2021 -synopsys: 2 +synopsys: 1 --- Hey y'all, it's been three months since my last blog post! You know what that means.. or should mean, at least. Yes, I'd quite like to have another long blog post done, but... Life is kinda trash right now, no motivation for writing, whatever. So over the coming week(s) or so, as a coping mechanism for the chaos that is the end of the semester, I'm gonna write a couple of really short posts (like this one) that might not even be coherent at all---this sentence sure isn't. diff --git a/pages/posts/2021-09-03-parsing-layout.md b/pages/posts/2021-09-03-parsing-layout.md index 31d2a62..86359f2 100644 --- a/pages/posts/2021-09-03-parsing-layout.md +++ b/pages/posts/2021-09-03-parsing-layout.md @@ -162,7 +162,7 @@ LClose | error {- parse error generated '}' -} ``` -We have unfortunately introduced some dragons, since the parser now needs to finesse the lexer state, meaning they must be interleaved _explicitly_, instead of explicitly (using a lazy list of tokens or similar). They must be in the same Monad. +We have unfortunately introduced some dragons, since the parser now needs to finesse the lexer state, meaning they must be interleaved _explicitly_, instead of being run in sequence (using a lazy list of tokens or similar). They must be in the same Monad. So. How do we implement this? @@ -869,7 +869,7 @@ Right }) ``` -I've thrown the code from this post up in an organised manner on [my Gitea](https://git.abby.how/abby/layout-parser/). The lexer worked out to be 130 lines, and the parser - just 81. +I've thrown the code from this post up in an organised manner on [my Gitea](https://git.amelia.how/amelia/layout-parser/). The lexer worked out to be 130 lines, and the parser - just 81. Here's why I favour this approach: diff --git a/pages/posts/2021-09-05-outsidein-x.md b/pages/posts/2021-09-05-outsidein-x.md new file mode 100644 index 0000000..5f40289 --- /dev/null +++ b/pages/posts/2021-09-05-outsidein-x.md @@ -0,0 +1,420 @@ +--- +title: Typing (GHC) Haskell in Haskell +subtitle: The OutsideIn(X) Elaboration Algorithm +date: September 5th, 2021 +public: false +--- + +Typing Haskell in Haskell, in addition to being a solved problem, is the name of [a paper] by Mark P. Jones that constructs, in detail, a solution to that problem. The goal of that paper is noble: a complete specification of Haskell's type system as an executable Haskell program. And, indeed, in 2000, when that paper was published, it _was_ a complete specification of Haskell's type system, depending on what you mean by Haskell. However, most people do not mean "Haskell 2010" when they say Haskell, let alone Haskell 98 - what the paper implements. Further, it's been 21 years! + +[a paper]: https://web.cecs.pdx.edu/~mpj/thih/thih.pdf + +When I say Haskell, personally, I mean "GHC's default language", and possibly throw in some 20 extensions on top anyway. Here's a small list of conveniences 2021 Haskell programmers are used to, but were implemented in the two decades since _Typing Haskell in Haskell_ was first published - or, in the case of FunDeps, were simply not standardised: + +- Rank-N types, a limited implementation of first-class polymorphism, let a Haskell programmer write `forall`s to the left of as many arrows as she wants. For a motivating example, take the ST monad, from which a value can be extracted using `runST`: + + ```haskell + runST :: (forall s. ST s a) -> a + ``` + + Since the type of the state token - `s` - is universally quantified, it's not "chosen" by the ST computation, but rather by `runST` itself, making sure that the computation can't adversarially "choose" an instantiation of `s` that violates referential transparency. + + Rank-N types were first implemented in GHC in November 2001, in [this commit](https://gitlab.haskell.org/ghc/ghc/-/commit/5e3f005d3012472e422d4ffd7dca5c21a80fca80). + +[rankn]: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/putting.pdf + +- Generalised algebraic data types (GADTs), which let us introduce local _equational constraints_ between types by means of pattern matching. I'm a big fan of GADTs, so much so that I paid 20 bucks to register the domain [gadt.fans](https://gadt.fans). The classic example of GADTs is a well-typed interpreter, where the type of each constructor constrains the return type of the interpreter: + + ```haskell + data Exp a where + Add :: Exp Int -> Exp Int -> Exp Int + IsZ :: Exp Int -> Exp Bool + If :: Exp Bool -> Exp a -> Exp a -> Exp a + Lit :: Int -> Exp Int + + eval :: Exp a -> a + eval (Lit i) = i + {- most cases omitted for brevity -} + ``` + + GADTs were first implemented in GHC in September 2004, in [this commit](https://gitlab.haskell.org/ghc/ghc/-/commit/23f40f0e9be6d4aa5cf9ea31d73f4013f8e7b4bd). + +- Functional dependencies, inspired by database theory, let a programmer specify that some of the arguments to one of their type classes is entirely determined by the value of some other argument. If that's a bit abstract, a more operational reading is that functional dependencies improve inferred types by adding new equalities. The classic example is this: + + ```haskell + class Collects c e | c -> e where + singleton :: e -> c + union :: c -> c -> c + ``` + + Without the functional dependency, the inferred type for the function `bagTwo` below would be `(Collects c e1, Collects c e2) => e1 -> e2 -> c`{.haskell}, implying that bagTwo is capable of placing two values of different types in the same collection `c`. + + ```haskell + bagTwo x y = singleton x `union` singleton y + ``` + + With the functional dependency `c -> e` in place, the two inferered constraints `(Collects c e1, Collects c e2)` _interact_ to introduce an equality `e1 ~ e2`, improving the inferred type of the function to + + ```haskell + bagTwo :: Collects c a => a -> a -> c + ``` + + Functional dependencies were first implemented in GHC in December 1999, in [this commit](https://gitlab.haskell.org/ghc/ghc/-/commit/297f714906efa8a76378c6fa6db3cd592f896749). The connection between database theory and type systems, integral in the design of functional dependencies for Haskell type classes, is made clear in [the original paper](http://web.cecs.pdx.edu/~mpj/pubs/fundeps-esop2000.pdf), section 5. + +- Type families, originally introduced as _associated types_, are, as [Richard Eisenberg put it](https://gitlab.haskell.org/ghc/ghc/-/issues/11080), "non-generative, non-injective symbols whose equational theory is given by GHC". Put another way, they're almost-but-not-quite functions between types. Type families are _weird_, and complicate type checking massively. For instance, consider the following program, taken from Storalek et al.'s "Injective Type Families for Haskell": + + ```haskell + class Manifold a where + type Base a + project :: a -> Base a + unproject :: Base a -> a + + id :: Manifold a => Base a -> Base a + id = project . unproject + ``` + + Does this program type check? Surprisingly, the answer is no! The reason is that the type variable `a` only appears under type families, and in the set of constraints, so GHC reports the function's type as ambiguous. + + To understand why this is problematic, imagine that we have two types `X`{.haskell} and `Y`{.haskell} such that `Base X = Base Y = [Double]`{.haskell}. Given a `vec :: [Double]`, what instance of `Manifold` should the call `id vec` use? We can't choose - we can only guess, and runtime behaviour that depends on a compiler guess is very much frowned upon! + + Type families were originally implemented ca. 2006, but I've been unable to track down the precise commit. I believe it was done as part of the patch which changed GHC's intermediate representation to System $F_C$ (we'll get to it) - this is backed up by this sentence from the conclusion of the $F_C$ paper: "At the same time, we re-implemented GHC’s support for newtypes and GADTs to work as outlined in §2 and added support for associated (data) types". + +All of these features interact with eachother in entirely non-trivial ways, creating a powerful source of GHC infelicities with $n^2$ magnitude. The interaction between GADTs and type families, for instance, mandates an elaboration algorithm which can cope with _local assumptions_ in a principled way, since GADTs can introduce equalities between existentials which interact with type family axioms non-trivially. Wobbly types just won't cut it. + +That's where $\operatorname{OutsideIn}$ comes in - or, more specifically, $\operatorname{OutsideIn}(X)$, since the elaboration algorithm is parametrised over the constraint domain $X$. This post is intended as a companion to [the JFP paper introducing OutsideIn](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/jfp-outsidein.pdf), not as a replacement. The core idea is that we can record where the local assumptions are introduced in a tree of _implication constraints_, built out of the constraints in our domain $X$, and these can be reduced - outside-in - to an $X$-specific solver. + +Diverging from the paper slightly, I'll implement the elaborator as a _bidirectional_ algorithm, which lets us take advantage of programmer-written type signatures. The signatures are there for a reason! It's silly to use type signatures as a source of complication (infer a type for the binding, then match it against the signature) rather than as a source of _simplification_. Plus - bidirectional type checking makes higher-rank types almost trivial - I think we can all agree that's a good thing, yeah? + +# The Problem Statement + +We're given a Haskell program - well, a program written in a proper subset of a proper superset of Haskell - and we want to tell whether it's type correct. Our superset extends Haskell 2010 to feature type families, GADTs, rank-N types and functional dependencies, but our subset doesn't contain most of Haskell's niceties, like definitions by equations, guards, or even `if`{.haskell}: you get `case`{.haskell}, and _you're going to like it_. + +Well, more than just telling whether or not the program is type correct, we want to produce an _elaborated program_ in a simpler language - GHC calls this "Core" - if and only if the program is correct, and report a (set of) good type errors otherwise. The elaborated program also has to be type correct, and, ideally, we have a _second_, much smaller type checker over the Core language that calls the big, complicated elaborator out on its bullshit. Because of this, the elaborator has to produce _evidence_ justifying its wilder claims. + +There are two kinds of evidence we need to produce: _coercions_ are inserted where the expected type of an expression is equal to its actual type in a non-trivial way. Consider the program below, and its elaboration to the right: + +
+ +```haskell +data T1 a where + TI :: T1 Int + TB :: T1 Bool + +foo :: T1 a -> a +foo x = case x of + TI -> 123 + TB -> True +``` + +```haskell +data T1 a where + TI :: (a ~# Int) => T1 a + TB :: (a ~# Bool) => T1 a + +foo :: T1 a -> a +foo x = case x of + TI phi -> 123 |> Sym phi + TB phi -> True |> Sym phi +``` + +
+ +This program, which uses GADTs (see `data ... where`{.haskell}), has two non-trivial equalities between types. In the `TI -> 123`{.haskell} case, we used an `Int`{.haskell}[^1] literal where a value of type `a` was expected. But in that branch, `a` is equal to `Int`{.haskell}! In the elaborated output, this non-trivial local equality is explicitly witnessed by a _coercion variable_ `phi :: a ~# Int`{.haskell}, and the use of `123 :: Int`{.haskell} at type `a` has to be mediated by a _cast_. + +[^1]: Actually, if you know how numeric literals desugar, you might know the actual elaboration produced here is different: `123` becomes `fromInteger @a ($NumInt |> Num (Sym phi)) (123 :: Integer)`{.haskell}. This is because it's totally legit to cast the `Num Int`{.haskell} dictionary to a `Num a`{.haskell} dictionary using the local equality, and, since `123`{.haskell} is sugar for `fromInteger @α (123 :: Integer)`{.haskell}, `α` gets solved to `a`, not `Int`{.haskell}. + +The other kind of evidence is not specific to GADTs, type families, or any other type fanciness: _dictionaries_ witness the existence of a type class `instance`{.haskell}, but, unlike coercions (which only exist to make the second type checker happy), exist at runtime. Consider the program below and its elaboration: + +
+ +```haskell +class S a where + s :: a -> String + +instance S Int where + s = show + +foo :: Int -> String +foo x = s (x + 123) +``` + +```haskell +data $S a = + $MkS { s :: a -> String } + +$dSInt :: S Int +$dSInt = $MkS @Int (show @Int $dShowInt) + +foo :: Int -> String +foo x = s @Int $dSInt ((+) @Int $dNumInt x 123) +``` + +
+ +Type `class`{.haskell}es are elaborated to `data`{.haskell} types, and `instance`{.haskell}s are compiled to actual proper values of those data types. When you apply a function with overloaded type - like `s`, `show` and `(+)` - the compiler inserts the value corresponding to the `instance`{.haskell} that was selected to satisfy the class constraint. Further, `instance`{.haskell}s with superclass constraints become functions from dictionaries to dictionaries, and superclasses on `class`{.haskell}es become values embedded in the dictionary, just like class methods. + +You'll also notice another artifact of elaboration here: the use of `s` at type `Int`{.haskell} became a _visible type application_ `s @Int`{.haskell}. This is, again, to satisfy the second type checker, but it can in principle be used as an actual implementation of polymorphism - one that doesn't box. See [Sixten](https://github.com/ollef/sixten) for a language that exploits this type passing to implement polymorphism without monomorphisation. Type applications are used in every polymorphic function application, not just those with class constraints. + +## Why it's hard + +GADTs complicate the problem of type inference in a way that's become rather famous: GADTs destroy the _principal types_ property. Recall: A **principal type** for a function $f$ is a type $\tau$ such that, $\Gamma \vdash f : \tau$ and, if $\Gamma \vdash f : \sigma$, then $\sigma$ is a substitution instance of $\tau$. Using less KaTeX, a principal type for a function is a _most general type_ for a type. For instance, the functions below are annotated with their principal types: + +```haskell +id :: a -> a +id x = x + +const :: a -> b -> a +const x _ = x +``` + +But now consider this program using GADTs: + +```haskell +data T a where + T1 :: Int -> T Bool + T2 :: T a + +test x y = case x of + T1 n -> n > 0 + T2 -> y +``` + +One can verify - and we will - that the function test types as either `test :: forall a. T a -> Bool -> Bool`{.haskell} or as `forall a. T a -> a -> a`{.haskell}, but neither of these types is an instance of the other! Let's look at why `test` checks with either of those types, with a _lot_ of detail - mimicking by hand the execution of the algorithm. Don't worry about all the terms I'll be throwing around: they'll all be explained later, I promise! + +
+ **`test :: forall a. T a -> Bool -> Bool`{.haskell}** + +The algorithm is in checking mode, since we have a type signature. + +1. Introduce a binding `x :: T a`{.haskell} into scope. We must check the body of the function against the type `Bool -> Bool`{.haskell} + +2. Introduce a binding `y :: Bool` into scope. We must check the body of the function against the type `Bool`{.haskell}. + +3. Check the `case`{.haskell} expression against the type `Bool`{.haskell}. There are two branches. + + * `T1 n -> n > 0`{.haskell}: + + * Instantiate the type of the constructor `T1 :: forall a. (a ~ Bool) => Int -> T a`{.haskell} with `a := X`{.haskell} to get the type `T1 :: a ~ Bool => Int -> T a`{.haskell}, where `a` is a _skolem_ type variable. The type variable `a` becomes a skolem and not a unification variable because it is an _existential_ of T1. + + * Introduce the local equality assumption `phi :: a ~ Bool`{.haskell} and the variable `n :: Int`{.haskell}. + + * Check that `n > 0 :: Bool`{.haskell}. For brevity, we'll take this to be one atomic step, which succeeds, but the real algorithm must treat all of those subexpressions independently. + + * `T2 -> y`{.haskell}. We must check that `y :: Bool`{.haskell}, which succeeds. + +Since all of these steps succeed (most of them are introducing variables and can't fail) - the program is type-correct. Note that in the branch with a local equality, our assumption that `a ~ Bool`{.haskell} wasn't used. + +
+ +
+ **`test :: forall a. T a -> a -> a`{.haskell}** + +The algorithm is in checking mode, since we have a type signature. + +1. Introduce a binding `x :: T a`{.haskell} into scope. We must check the body of the function against the type `a -> a`{.haskell} + +2. Introduce a binding `y :: a` into scope. We must check the body of the function against the type `a`{.haskell}. + +3. Check the `case`{.haskell} expression against the type `Bool`{.haskell}. There are two branches. + + * `T1 n -> n > 0`{.haskell}: + + * Instantiate the type of the constructor `T1 :: forall a. (a ~ Bool) => Int -> T a`{.haskell} with `a := X`{.haskell} to get the type `T1 :: a ~ Bool => Int -> T a`{.haskell}, where `a` is a _skolem_ type variable. The type variable `a` becomes a skolem and not a unification variable because it is an _existential_ of T1. + + * Introduce the local equality assumption `phi :: a ~ Bool`{.haskell} and the variable `n :: Int`{.haskell}. + + * Check that `n > 0 :: a`{.haskell}. We infer that `n > 0 :: Bool`{.haskell}, and we must unify `Bool ~ a`{.haskell}. This unification succeeds because of the given equality `phi :: a ~ Bool`{.haskell}, which we are free to invert. + + * `T2 -> y`{.haskell}. We must check that `y :: a`{.haskell}, which succeeds. + +Since all of these steps succeed (most of them are introducing variables and can't fail) - the program is type-correct. In this typing, compared with the previous, we made use of the assumption `phi :: a ~ Bool` brought into scope by the match against the constructor `T1 n`. + +
+ +The execution trace for both cases is remarkably similar - the only difference is in that if the function is typed as `T a -> a -> a`{.haskell}, we must make use of the local equality brought into scope to justify that we're allowed to use a value nominally of type `Bool`{.haskell} as one of type `a`. We are free to do this, but it's not obvious if, without a type annotation to guide us, we should. Consider now the following very minor alteration to test: + +```haskell +test x y = case x of + T1 n -> n > 0 + T2 -> not y +``` + +The only possible type for this program is `T a -> Bool -> Bool`{.haskell}, and so, we can decide without any major complications that the GADT equality should _not_ be used. + +# How To Check Types + +In this section we'll solve the infinitely simpler problem of elaborating a language with rank-N types and type classes - including functional dependencies - but crucially, no GADTs. To do this we'll use a _bidirectional_, _constraint-based_ elaboration algorithm. + +First, bidirectional means that, unlike in a type _inference_ system, type information flows both in and out of the algorithm. Practically speaking, we have two functions to implement the case where type information is an input to the algorithm (`check`{.haskell}) and one where type information is a return from the algorithm (`infer`{.haskell}). + +```haskell +infer :: Raw.Expr -> Elab (Core.Term, Core.Type) +check :: Raw.Expr -> Core.Type -> Elab Core.Term +``` + +If you know how to infer a type for an expression `e` but you need to check it against a known type `wanted_type`, you can do it by unification, whereas if you know how to check an expression `f` against a type but you need to infer a type for it, you can do it by inventing a new _metavariable_ and checking against that[^2]: + +[^2]: In the OutsideIn(X) paper, metavariables are known as _unification variables_. The term _metavariable_ is common in the dependently-typed world, whereas _unification variable_ is more common among Haskell and ML researchers. + +
+ +```haskell +check e wanted_type = do + (elab, actual_type) <- infer x + unify wanted_type actual_type + pure elab +``` + +```haskell +infer f = do + ty <- newMeta + elab <- check f ty + pure (elab, ty) +``` + +
+ +Constraint-based means that, at least conceptually, the algorithm works by first generating constraints by walking through the AST (we do this bidirectionally), and only later solving the generated constraints. But, as a very fruitful optimisation, there are cases where the constraints need not be stashed away for later: If we want to solve a unification problem, for instance, where a metavariable is being compared against a concrete type, and we're free to solve the variable with that type, we might as well do it inline. + +_Elaboration_ is a natural extension of "type checking" in which the program is both checked and transformed into a simpler intermediate representation in the same step. The name "type checker" sort-of implies that the output is a boolean (or, more realistically, a list of errors): this is rarely true in practice, but I still prefer the use of the name "elaborator" to make clear that the output is a different _language_ from the input, and not merely a type-annotated version of the input. + +I'm going to start by talking about the intermediate language we'll elaborate into, _System $F_C$, first. This is because of an assumption I'm making: I'm assuming most of my readers are familiar with Haskell - at least in passing - but not very familiar with GHC's intermediate language. That's why we start there! + +## Our Target Language + +System $F_C$, as the name kind-of sort-of implies, is a superset of System $F$, the _second-order_ lambda calculus. For those not in the loop, System F has all the same features of a normal typed lambda calculus (variables, lambda abstraction, application, algebraic data types, and pattern matching[^3]), but additionally features _first class polymorphism_. Roughly, this means that in System F, a `forall`{.haskell} type can appear everywhere a "normal" type can appear - you could form the type `[forall a. a -> a]`{.haskell} of "lists of identity functions", for instance. + +[^3]: If you disagree with the inclusion of algebraic data types and pattern matching in the list of features of a "normal typed lambda calculus"---there's nothing you can do about it, this is my blog, lol. + +Now, this doesn't mean that first class polymorphism is available to languages that elaborate into System $F_C$ - GHC, for instance, struggled with what they call "impredicative polymorphism" for years, up until very recently. Amulet did a slightly better job because, being a research toy and not a production compiler (that happens to be also be a research toy), there was less code to move around by implementing support for first-class polymorphism. + +Since `forall`{.haskell} is a new type former, it also has a corresponding introduction form and elimination form. The introduction rule says that if you can build a term `e : t` in a context where `a` is a type variable of kind `k`, then the term `Λ (a :: k). e` has type `forall (a :: k). σ`{.haskell}. To stick with ASCII for "control" symbols, I'm going to write `Λ (a :: k)` as `\ @(a :: k)`{.haskell}, omitting `κ` if it is obvious - Also, I'm sticking with Haskell notation, even if `::` should really mean cons. + +Similarly, the elimination rule says that to consume an expression `e :: forall (a :: k). t`{.haskell}, what we need to do is come up with a _type_ `s :: k`{.haskell}. Then we can _instantiate_ (using a different word so as to not overload "apply") `e`{.haskell} at `s`{.haskell} to get a term `e @s :: t[s/a]`{.haskell} - where `t[s/a]` denotes the substitution of `s` for `a` in `t`, avoiding capture. + +Here's a simple Haskell program, and its translation into the notation I'll use for $F_C$. We'll go over it afterwards. + +
+ +```haskell +data List a + = Nil + | Cons a (List a) + +map :: (a -> b) -> List a -> List a +-- this line intentionally left blank +map f (Cons x xs) = Cons (f x) (map f xs) +map f Nil = Nil +``` + +```haskell +data List :: * -> * where + Nil :: forall a. List a + Cons :: forall a. a -> List a -> List a + +map :: forall a b. (a -> b) -> List a -> List a +map @a @b f x = case x of + Cons x xs -> Cons @b (f x) (map @a @b f xs) + Nil -> Nil @b +``` + +
+ +Let's go over the differences: + +* In Haskell, we allow datatype declarations using the Haskell 98 syntax, but in $F_C$ all data types are given in GADT syntax. Furthermore, `List`{.haskell} was given a kind annotation when it was elaborated - the kind of `List`{.haskell} says it maps ground types to ground types. By "ground type" I mean something that's potentially inhabited, e.g. `Int`{.haskell} or `Void`{.haskell}, but not `Maybe`. + + Where does the kind annotation come from? Well, we know `List` will have a function kind since it has one argument, and we know its return kind will be `*`{.haskell} since all data types are in `*`{.haskell}. That means we kind-check the constructors with `List :: κ -> a`{.haskell} in scope, where `κ` is a fresh metavariable. The type of `Nil`{.haskell} doesn't fix `κ`, but the type of `Cons`{.haskell} - `a` is used on the left of an arrow, so it must have kind `*`. + +* Haskell has definition by equations, but in $F_C$ we simply have type signatures and definitions. We can translate the equations into a case tree using a rather involved - but mechanical - process, and, to avoid that complication, the subset of Haskell our elaborator works will not support equations. It's mostly immaterial to elaboration, anyway. + +* In Haskell, the type signature `map :: (a -> b) -> List a -> List b`{.haskell} is written with implicit binders for the type variables `a` and `b`, so that they're seemingly free. This is not the case, of course, and so in $F_C$ we must write out what `forall`{.haskell}s we mean. This is less relevant in this case, where there are no free type variables in the environment, but specifying `forall`{.haskell}s is essential when we have `ScopedTypeVariables`. + +* Finally, all of the polymorphism implicit in the Haskell version of the program was made explicit in its elaboration into $F_C$. For instance, the type of the `map`{.haskell} function has two `forall`{.haskell}s, so its definition must begin with a corresponding number of `\@`{.haskell}s (which I moved onto the RHS for presentation purposes - don't want lines getting too wide). + + Similarly, the list `Cons`{.haskell}tructors were used as expressions of type `List a` in Haskell, but their $F_C$ types start with a `forall`{.haskell}, meaning we have to instantiate them - `Nil @b`{.haskell}, `Cons @b`{.haskell} - at the return type of the `map` function. + +We represent the language using a data type. Syntax productions in the language become constructors of our data type. For clarity of presentation, I'll use `Text`{.haskell}s for variable names. This is a bad idea, and it'll make a lot of you very angry - for good reason! Dealing with binders is _hard_, and using strings for identifiers is quite possibly the worst solution. It'd be more principled to use de Bruijn indices, or locally nameless, or something. But - that's a needless complication, so, in the interest of clarity, I'll just use strings. + +Since our language contains type applications, we "need" to define types before expressions. Well, this is a Haskell program, so we don't _need_ to - Haskell programs are not lists of definitions, but rather _directed graphs_ of definitions, so that source order doesn't matter - but for clarity, we define the type of types before the type of expressions. + +```haskell +module Core where + +import qualified Data.Text as T +import Data.Text (Text) + +data Kind + = TypeKi + -- ^ The kind '*' + | ConstraintKi + -- ^ The kind 'Constraint' + | FunKi Kind Kind + -- ^ κ → κ + deriving (Eq, Show) + +data Type + = VarTy Text Kind + -- ^ Type variables α + | AppTy Type Type + -- ^ The type being applied is never a constructor, + -- always another AppTy or a VarTy. + | ConTy Text [Type] + -- ^ Type constructor applied to some arguments. + | ForAllTy Text Kind Type + -- ^ Polymorphic types + | FunTy Type Type + -- ^ Function types + deriving (Eq, Show) +``` + +Throughout the language, variables (resp. type variables) are annotated with the type (resp. kind) with which they are introduced. More, our type of expressions unifies `\ @a`{.haskell} and `\ x`{.haskell}, as well as both application forms, by delegating to `Binder`{.haskell} and `Arg`{.haskell} types. + +```{.haskell style="padding-bottom: 0"} +data Binder = TypeBinder Text | ExprBinder Text + deriving (Eq, Show) + +data Arg = TypeArg Type | ExprArg Expr + deriving (Eq, Show) + +data Expr + = Var Text Type + | App Expr Arg + | Lam Binder Expr +-- continues +``` + +For `Let`{.haskell}, we introduce yet another auxiliary type. A `Bind`{.haskell} represents a _binding group_, a group of mutually recursive definitions. Binding groups do not correspond 1:1 with `let`{.haskell}s in Haskell, for instance, the Haskell program on the left is elaborated into the Core expression on the right: + +
+ +```haskell +let quux x = bar (x - 1) + foo = 1 + bar x = quux x + foo +in foo +``` + +```haskell +Let (NonRec "foo" (Lit 1)) $ + Let (Rec [ ("quux", Lam (ExprBinder ...) ... + , ("bar", Lam (ExprBinder ...) ...) ] $ + Var "foo" +``` + +
+ +As you can probably imagine, the way I arrived at this definition involves.. Graphs. Yes, it's unfortunate, but it's the only way to correctly describe how Haskell declaration blocks - that includes the top level - are type checked. The Haskell report mandates that declaration groups - in the top level, a `let`{.haskell} expression or a `where`{.haskell} clause - should be sorted into strongly connected components, and type-checked in dependency order. Each of these connected components becomes a `Rec`{.haskell} binding! + +We define the auxiliary `Bind`{.haskell} type.. somewhere else, since we still have cases to add to the `Expr`{.haskell}. It's either a connected graph of mutually recursive binders, containing a list of pairs of names and expressions, or a single binder - in which case we unpack the pair. + +```{.haskell style="padding-top: 0; padding-bottom: 0;"} +-- continued + | Let [Bind] Expr + +data Bind + = NonRec Text Expr + | Rec [(Text, Expr)] + deriving (Eq, Show) +-- continues +``` \ No newline at end of file diff --git a/rubtmpjd3t_2bh.log b/rubtmpjd3t_2bh.log deleted file mode 100644 index e742a57..0000000 --- a/rubtmpjd3t_2bh.log +++ /dev/null @@ -1,232 +0,0 @@ -This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2021/Arch Linux) (preloaded format=pdflatex 2021.5.25) 26 AUG 2021 19:58 -entering extended mode - restricted \write18 enabled. - %&-line parsing enabled. -**\nonstopmode \input{/home/me/Sync/Projects/blag/rubtmpjd3t_2bh.tex} -(/home/me/Sync/Projects/blag/rubtmpjd3t_2bh.tex -(/usr/share/texmf-dist/tex/latex/base/article.cls -Document Class: article 2020/04/10 v1.4m Standard LaTeX document class -(/usr/share/texmf-dist/tex/latex/base/size10.clo -File: size10.clo 2020/04/10 v1.4m Standard LaTeX file (size option) -) -\c@part=\count179 -\c@section=\count180 -\c@subsection=\count181 -\c@subsubsection=\count182 -\c@paragraph=\count183 -\c@subparagraph=\count184 -\c@figure=\count185 -\c@table=\count186 -\abovecaptionskip=\skip47 -\belowcaptionskip=\skip48 -\bibindent=\dimen138 -) -(/usr/share/texmf-dist/tex/latex/preview/preview.sty -Package: preview 2017/04/24 12.3 (AUCTeX/preview-latex) - -(/usr/share/texmf-dist/tex/generic/luatex85/luatex85.sty -Package: luatex85 2016/06/15 v1.4 pdftex aliases for luatex -) -(/usr/share/texmf-dist/tex/latex/preview/prtightpage.def -\PreviewBorder=\dimen139 -) -\pr@snippet=\count187 -\pr@box=\box47 -\pr@output=\toks15 -) -(/usr/share/texmf-dist/tex/latex/amsmath/amsmath.sty -Package: amsmath 2020/09/23 v2.17i AMS math features -\@mathmargin=\skip49 - -For additional information on amsmath, use the `?' option. -(/usr/share/texmf-dist/tex/latex/amsmath/amstext.sty -Package: amstext 2000/06/29 v2.01 AMS text - -(/usr/share/texmf-dist/tex/latex/amsmath/amsgen.sty -File: amsgen.sty 1999/11/30 v2.0 generic functions -\@emptytoks=\toks16 -\ex@=\dimen140 -)) -(/usr/share/texmf-dist/tex/latex/amsmath/amsbsy.sty -Package: amsbsy 1999/11/29 v1.2d Bold Symbols -\pmbraise@=\dimen141 -) -(/usr/share/texmf-dist/tex/latex/amsmath/amsopn.sty -Package: amsopn 2016/03/08 v2.02 operator names -) -\inf@bad=\count188 -LaTeX Info: Redefining \frac on input line 234. -\uproot@=\count189 -\leftroot@=\count190 -LaTeX Info: Redefining \overline on input line 399. -\classnum@=\count191 -\DOTSCASE@=\count192 -LaTeX Info: Redefining \ldots on input line 496. -LaTeX Info: Redefining \dots on input line 499. -LaTeX Info: Redefining \cdots on input line 620. -\Mathstrutbox@=\box48 -\strutbox@=\box49 -\big@size=\dimen142 -LaTeX Font Info: Redeclaring font encoding OML on input line 743. -LaTeX Font Info: Redeclaring font encoding OMS on input line 744. -\macc@depth=\count193 -\c@MaxMatrixCols=\count194 -\dotsspace@=\muskip16 -\c@parentequation=\count195 -\dspbrk@lvl=\count196 -\tag@help=\toks17 -\row@=\count197 -\column@=\count198 -\maxfields@=\count199 -\andhelp@=\toks18 -\eqnshift@=\dimen143 -\alignsep@=\dimen144 -\tagshift@=\dimen145 -\tagwidth@=\dimen146 -\totwidth@=\dimen147 -\lineht@=\dimen148 -\@envbody=\toks19 -\multlinegap=\skip50 -\multlinetaggap=\skip51 -\mathdisplay@stack=\toks20 -LaTeX Info: Redefining \[ on input line 2923. -LaTeX Info: Redefining \] on input line 2924. -) -(/usr/share/texmf-dist/tex/latex/amsfonts/amssymb.sty -Package: amssymb 2013/01/14 v3.01 AMS font symbols - -(/usr/share/texmf-dist/tex/latex/amsfonts/amsfonts.sty -Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support -\symAMSa=\mathgroup4 -\symAMSb=\mathgroup5 -LaTeX Font Info: Redeclaring math symbol \hbar on input line 98. -LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold' -(Font) U/euf/m/n --> U/euf/b/n on input line 106. -)) -(/usr/share/texmf-dist/tex/latex/jknapltx/mathrsfs.sty -Package: mathrsfs 1996/01/01 Math RSFS package v1.0 (jk) -\symrsfs=\mathgroup6 -) -(/usr/share/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty -(/usr/share/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty -(/usr/share/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty -(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex -\pgfutil@everybye=\toks21 -\pgfutil@tempdima=\dimen149 -\pgfutil@tempdimb=\dimen150 - -(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.tex)) -(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def -\pgfutil@abb=\box50 -) -(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex -(/usr/share/texmf-dist/tex/generic/pgf/pgf.revision.tex) -Package: pgfrcs 2020/12/27 v3.1.8b (3.1.8b) -)) -Package: pgf 2020/12/27 v3.1.8b (3.1.8b) - -(/usr/share/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty -(/usr/share/texmf-dist/tex/latex/graphics/graphicx.sty -Package: graphicx 2020/09/09 v1.2b Enhanced LaTeX Graphics (DPC,SPQR) - -(/usr/share/texmf-dist/tex/latex/graphics/keyval.sty -Package: keyval 2014/10/28 v1.15 key=value parser (DPC) -\KV@toks@=\toks22 -) -(/usr/share/texmf-dist/tex/latex/graphics/graphics.sty -Package: graphics 2020/08/30 v1.4c Standard LaTeX Graphics (DPC,SPQR) - -(/usr/share/texmf-dist/tex/latex/graphics/trig.sty -Package: trig 2016/01/03 v1.10 sin cos tan (DPC) -) -(/usr/share/texmf-dist/tex/latex/graphics-cfg/graphics.cfg -File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration -) -Package graphics Info: Driver file: pdftex.def on input line 105. - -(/usr/share/texmf-dist/tex/latex/graphics-def/pdftex.def -File: pdftex.def 2020/10/05 v1.2a Graphics/color driver for pdftex -)) -\Gin@req@height=\dimen151 -\Gin@req@width=\dimen152 -) -(/usr/share/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty -(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex -Package: pgfsys 2020/12/27 v3.1.8b (3.1.8b) - -(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex -\pgfkeys@pathtoks=\toks23 -\pgfkeys@temptoks=\toks24 - -(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.tex -\pgfkeys@tmptoks=\toks25 -)) -\pgf@x=\dimen153 -\pgf@y=\dimen154 -\pgf@xa=\dimen155 -\pgf@ya=\dimen156 -\pgf@xb=\dimen157 -\pgf@yb=\dimen158 -\pgf@xc=\dimen159 -\pgf@yc=\dimen160 -\pgf@xd=\dimen161 -\pgf@yd=\dimen162 -\w@pgf@writea=\write3 -\r@pgf@reada=\read2 -\c@pgf@counta=\count266 -\c@pgf@countb=\count267 -\c@pgf@countc=\count268 -\c@pgf@countd=\count269 -\t@pgf@toka=\toks26 -\t@pgf@tokb=\toks27 -\t@pgf@tokc=\toks28 -\pgf@sys@id@count=\count270 - -(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg -File: pgf.cfg 2020/12/27 v3.1.8b (3.1.8b) -) -Driver file for pgf: pgfsys-pdftex.def - -(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def -File: pgfsys-pdftex.def 2020/12/27 v3.1.8b (3.1.8b) - -(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.def -File: pgfsys-common-pdf.def 2020/12/27 v3.1.8b (3.1.8b) -))) -(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex -File: pgfsyssoftpath.code.tex 2020/12/27 v3.1.8b (3.1.8b) -\pgfsyssoftpath@smallbuffer@items=\count271 -\pgfsyssoftpath@bigbuffer@items=\count272 -) -(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex -File: pgfsysprotocol.code.tex 2020/12/27 v3.1.8b (3.1.8b) -)) -(/usr/share/texmf-dist/tex/latex/xcolor/xcolor.sty -Package: xcolor 2016/05/11 v2.12 LaTeX color extensions (UK) - -(/usr/share/texmf-dist/tex/latex/graphics-cfg/color.cfg -File: color.cfg 2016/01/02 v1.6 sample color configuration -) -! Interruption. - ...sextension \else \@classoptionslist - ,\fi \@curroptions , -l.216 \ProcessOptions\relax - -? -! Emergency stop. - ...sextension \else \@classoptionslist - ,\fi \@curroptions , -l.216 \ProcessOptions\relax - -End of file on the terminal! - - -Here is how much of TeX's memory you used: - 3149 strings out of 478994 - 50546 string characters out of 5864751 - 338722 words of memory out of 5000000 - 20600 multiletter control sequences out of 15000+600000 - 403430 words of font info for 27 fonts, out of 8000000 for 9000 - 1141 hyphenation exceptions out of 8191 - 117i,0n,119p,402b,36s stack positions out of 5000i,500n,10000p,200000b,80000s -! ==> Fatal error occurred, no output PDF file produced! diff --git a/site b/site new file mode 100755 index 0000000..2940354 Binary files /dev/null and b/site differ diff --git a/site.hs b/site.hs index 18dd8d4..a68a05a 100644 --- a/site.hs +++ b/site.hs @@ -3,6 +3,8 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE BlockArguments #-} {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE DeriveAnyClass #-} import Control.DeepSeq (rnf) import Control.Concurrent @@ -51,6 +53,8 @@ import Data.Hashable (Hashable (hashWithSalt)) import GHC.Stack import Text.Read (readMaybe) import GHC.Show (showCommaSpace) +import Data.Traversable +import qualified Data.Text.Lazy as LT readerOpts :: ReaderOptions readerOpts = def { readerExtensions = pandocExtensions @@ -73,11 +77,11 @@ writerOptions = do rssfeed :: FeedConfiguration rssfeed - = FeedConfiguration { feedTitle = "Abigail's Blag: Latest articles" + = FeedConfiguration { feedTitle = "Amelia's Blag: Latest articles" , feedDescription = "" - , feedAuthorName = "Abigail Magalhães" - , feedAuthorEmail = "magalhaes.alcantara@pucpr.edu.br" - , feedRoot = "https://abby.how" + , feedAuthorName = "Amélia" + , feedAuthorEmail = "me@amelia.how" + , feedRoot = "https://amelia.how" } conf :: Configuration @@ -86,10 +90,9 @@ conf = def { destinationDirectory = ".site" , tmpDirectory = ".store/tmp" , deployCommand = "./sync" } -katexFilter :: IORef KatexCache -> Pandoc -> Compiler Pandoc +katexFilter :: MVar KatexCache -> Pandoc -> Compiler Pandoc katexFilter cacheVar (Pandoc meta doc) = do - initCache <- unsafeCompiler (readIORef cacheVar) id <- compilerUnderlying <$> compilerAsk t <- getMetadata id @@ -110,7 +113,7 @@ katexFilter cacheVar (Pandoc meta doc) = go :: String -> [String] -> Inline -> Compiler Inline go id abbrevs (Math kind math) = unsafeCompiler $ do - cache <- readIORef cacheVar + cache <- readMVar cacheVar case HMap.lookup (id, kind, math) (spanMap cache) of Just x -> pure (RawInline "html" x) Nothing -> do @@ -119,7 +122,7 @@ katexFilter cacheVar (Pandoc meta doc) = (contents, _) <- readProcessBS "node_modules/.bin/katex" args . BS.fromStrict . T.encodeUtf8 $ math let text = T.init . T.init . T.decodeUtf8 . BS.toStrict $ contents - atomicModifyIORef' cacheVar (\m -> (bumpCacheEntry cache id abbrevs kind text math, ())) + modifyMVar cacheVar (\m -> pure (bumpCacheEntry cache id abbrevs kind text math, ())) pure $ RawInline "html" text go id _ x = pure x @@ -200,7 +203,7 @@ saveSynopsys (Pandoc meta doc) = case dropWhile (not . isParagraph) doc of p:ps -> do - saveSnapshot "synopsys" =<< makeItem (map removeFootnotes (take n (p:ps))) + saveSnapshot "synopsys-block" =<< makeItem (map removeFootnotes (take n (p:ps))) pure () [] -> pure () pure $ Pandoc meta doc @@ -254,23 +257,12 @@ saveTableOfContents (Pandoc meta input) = toc :: Block toc = list (into headers) -sassImporter :: SassImporter -sassImporter = SassImporter 0 go where - go "normalize" _ = do - c <- readFile "node_modules/normalize.css/normalize.css" - pure [ SassImport { importPath = Nothing - , importAbsolutePath = Nothing - , importSource = Just c - , importSourceMap = Nothing - } ] - go _ _ = pure [] - -setup :: IO (IORef KatexCache) +setup :: IO (MVar KatexCache) setup = do setEnv "AMC_LIBRARY_PATH" "/usr/lib/amuletml/lib/" loadCache -compiler :: IORef KatexCache -> Compiler (Item String) +compiler :: MVar KatexCache -> Compiler (Item String) compiler katexCache = do wops <- writerOptions pandocCompilerWithTransformM readerOpts wops $ @@ -279,7 +271,6 @@ compiler katexCache = do >=> saveSynopsys >=> saveWordCount >=> saveTableOfContents - >=> pure . addLanguageTag main :: IO () main = setup >>= \katexCache -> hakyllWith conf $ do @@ -301,9 +292,21 @@ main = setup >>= \katexCache -> hakyllWith conf $ do match "css/*.scss" $ do route $ setExtension "css" - compile $ sassCompilerWith def { sassOutputStyle = SassStyleCompressed - , sassImporters = Just [ sassImporter ] - } + compile $ do + imports <- unsafeCompiler $ newMVar ([] :: [(String, String)]) + let add f p = modifyMVar imports (\x -> pure ((f, p):x, [])) + + body <- sassCompilerWith def + { sassOutputStyle = SassStyleCompressed + , sassImporters = Just [ SassImporter 0 add ] + } + + list <- unsafeCompiler $ takeMVar imports + for list $ \(req, path) -> do + load (fromFilePath ("css/" ++ reverse (dropWhile (/= '.') (reverse req)) ++ "scss")) + :: Compiler (Item String) + + pure body match "diagrams/**/*.tex" $ do route $ setExtension "svg" @@ -326,12 +329,11 @@ main = setup >>= \katexCache -> hakyllWith conf $ do >>= loadAndApplyTemplate "templates/default.html" postCtx >>= relativizeUrls - loadSnapshot id "synopsys" - >>= saveSnapshot "synopsys" + loadSnapshot id "synopsys-block" + >>= saveSnapshot "synopsys-text" . writePandocWith wops . fmap (Pandoc mempty) - pure r match "pages/posts/*.lhs" $ version "raw" $ do @@ -375,7 +377,7 @@ main = setup >>= \katexCache -> hakyllWith conf $ do path <- toFilePath <$> getUnderlying contents <- itemBody <$> getResourceBody debugCompiler ("Loaded syntax definition from " ++ show path) - res <- unsafeCompiler (Sky.parseSyntaxDefinitionFromString path contents) + let res = Sky.parseSyntaxDefinitionFromText path (LT.pack contents) _ <- saveSnapshot "syntax" =<< case res of Left e -> fail e Right x -> makeItem x @@ -387,7 +389,7 @@ main = setup >>= \katexCache -> hakyllWith conf $ do route idRoute compile $ do let feedCtx = postCtx <> bodyField "description" - posts <- fmap (take 10) . recentFirst =<< onlyPublic =<< loadAllSnapshots ("pages/posts/*" .&&. hasNoVersion) "synopsys" + posts <- fmap (take 10) . recentFirst =<< onlyPublic =<< loadAllSnapshots ("pages/posts/*" .&&. hasNoVersion) "synopsys-text" renderRss rssfeed feedCtx posts onlyPublic :: [Item String] -> Compiler [Item String] @@ -401,7 +403,7 @@ onlyPublic = filterM isPublic where postCtx :: Context String postCtx = dateField "date" "%B %e, %Y" - <> snapshotField "synopsys" "synopsys" + <> snapshotField "synopsys" "synopsys-text" <> snapshotField "words" "wc" <> snapshotField' render "toc" "table-of-contents" <> defaultContext @@ -486,7 +488,7 @@ pathFromTitle meta = foldMapM :: (Monad w, Monoid m, Foldable f) => (a -> w m) -> f a -> w m foldMapM k = foldr (\x y -> do { m <- k x; (m <>) <$> y }) (pure mempty) -loadCache :: HasCallStack => IO (IORef KatexCache) +loadCache :: HasCallStack => IO (MVar KatexCache) loadCache = do t <- doesFileExist ".katex_cache" let fixup (a, b, c) = KatexCache (HMap.fromList a) (HMap.fromList b) (HMap.fromList c) @@ -494,16 +496,16 @@ loadCache = do then (fixup <$> decodeFile ".katex_cache") `catch` \e -> const (print e *> pure (KatexCache mempty mempty mempty)) (e :: SomeException) else pure (KatexCache mempty mempty mempty) - var <- newIORef map + var <- newMVar map pure var -flushCache :: IORef KatexCache -> IO () +flushCache :: MVar KatexCache -> IO () flushCache var = do - KatexCache x y z <- readIORef var - Data.Binary.encodeFile ".katex_cache" (HMap.toList x, HMap.toList y, HMap.toList z) + withMVar var $ \(KatexCache x y z) -> do + Data.Binary.encodeFile ".katex_cache" (HMap.toList x, HMap.toList y, HMap.toList z) -invalidateCache :: Identifier -> [String] -> IORef KatexCache -> Compiler KatexCache -invalidateCache id abbrevs cacheVar = unsafeCompiler $ atomicModifyIORef' cacheVar (\x -> (go x, go x)) where +invalidateCache :: Identifier -> [String] -> MVar KatexCache -> Compiler KatexCache +invalidateCache id abbrevs cacheVar = unsafeCompiler $ modifyMVar cacheVar (\x -> pure (go x, go x)) where currentValues = map (\x -> (T.pack (takeWhile (/= ':') (tail x)), T.pack (tail (dropWhile (/= ':') (tail x))))) $ filter (not . isPrefixOf "-") abbrevs ident = show id @@ -528,4 +530,25 @@ data KatexCache instance Hashable MathType where hashWithSalt s DisplayMath = hashWithSalt s (0 :: Int) - hashWithSalt s InlineMath = hashWithSalt s (1 :: Int) \ No newline at end of file + hashWithSalt s InlineMath = hashWithSalt s (1 :: Int) + +deriving instance Binary Block +deriving instance Binary Inline +deriving instance Binary Format +deriving instance Binary ListNumberStyle +deriving instance Binary ListNumberDelim +deriving instance Binary Caption +deriving instance Binary Alignment +deriving instance Binary ColWidth +deriving instance Binary TableHead +deriving instance Binary TableBody +deriving instance Binary TableFoot +deriving instance Binary QuoteType +deriving instance Binary Citation +deriving instance Binary Row +deriving instance Binary MathType +deriving instance Binary RowHeadColumns +deriving instance Binary CitationMode +deriving instance Binary Cell +deriving instance Binary RowSpan +deriving instance Binary ColSpan \ No newline at end of file diff --git a/stack.yaml b/stack.yaml index 7f9fb9d..62b041c 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,6 +1,5 @@ -resolver: lts-16.20 +resolver: lts-18.16 extra-deps: +- hakyll-4.15.1.0@sha256:df90fdb1e7e09e90557ad23a6d402ce042f820f690595e7e73db82220edcadcf,9924 - hakyll-sass-0.2.4@sha256:4d2fbd8b63f5ef15483fc6dda09e10eefd63b4f873ad38dec2a3607eb504a8ba,939 -- hsass-0.8.0@sha256:05fb3d435dbdf9f66a98db4e1ee57a313170a677e52ab3a5a05ced1fc42b0834,2899 -- hlibsass-0.1.10.1@sha256:08db56c633e9a83a642d8ea57dffa93112b092d05bf8f3b07491cfee9ee0dfa5,2565 \ No newline at end of file diff --git a/stack.yaml.lock b/stack.yaml.lock index 367ecc8..0a05467 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -4,6 +4,13 @@ # https://docs.haskellstack.org/en/stable/lock_files packages: +- completed: + hackage: hakyll-4.15.1.0@sha256:df90fdb1e7e09e90557ad23a6d402ce042f820f690595e7e73db82220edcadcf,9924 + pantry-tree: + size: 8860 + sha256: 474bd1e22b8eb6c7ad8e397c1c6741204fff4b30ebc5d9d47576c43820d17e13 + original: + hackage: hakyll-4.15.1.0@sha256:df90fdb1e7e09e90557ad23a6d402ce042f820f690595e7e73db82220edcadcf,9924 - completed: hackage: hakyll-sass-0.2.4@sha256:4d2fbd8b63f5ef15483fc6dda09e10eefd63b4f873ad38dec2a3607eb504a8ba,939 pantry-tree: @@ -11,23 +18,9 @@ packages: sha256: c03e74e71d010f009b8d972efc31fbd6dd25183e6d9afbec55f4b7f0d4a74b47 original: hackage: hakyll-sass-0.2.4@sha256:4d2fbd8b63f5ef15483fc6dda09e10eefd63b4f873ad38dec2a3607eb504a8ba,939 -- completed: - hackage: hsass-0.8.0@sha256:05fb3d435dbdf9f66a98db4e1ee57a313170a677e52ab3a5a05ced1fc42b0834,2899 - pantry-tree: - size: 1448 - sha256: b25aeb947cb4e0b550f8a6f226d06503ef0edcb54712ad9cdd4fb2b05bf16c7c - original: - hackage: hsass-0.8.0@sha256:05fb3d435dbdf9f66a98db4e1ee57a313170a677e52ab3a5a05ced1fc42b0834,2899 -- completed: - hackage: hlibsass-0.1.10.1@sha256:08db56c633e9a83a642d8ea57dffa93112b092d05bf8f3b07491cfee9ee0dfa5,2565 - pantry-tree: - size: 11229 - sha256: 39b62f1f3f30c5a9e12f9c6a040d6863edb5ce81951452e649152a18145ee1bc - original: - hackage: hlibsass-0.1.10.1@sha256:08db56c633e9a83a642d8ea57dffa93112b092d05bf8f3b07491cfee9ee0dfa5,2565 snapshots: - completed: - size: 532177 - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/16/20.yaml - sha256: 0e14ba5603f01e8496e8984fd84b545a012ca723f51a098c6c9d3694e404dc6d - original: lts-16.20 + size: 586286 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/16.yaml + sha256: cdead65fca0323144b346c94286186f4969bf85594d649c49c7557295675d8a5 + original: lts-18.16 diff --git a/static/default.css b/static/default.css deleted file mode 100644 index 98aedd9..0000000 --- a/static/default.css +++ /dev/null @@ -1,10 +0,0 @@ -body{color:black;font-size:16px;margin:0px auto 0px -auto;width:80%;font-family:Fira Sans, sans-serif}div#header{border-bottom:2px -solid black;margin-bottom:30px;padding:12px 0px 12px 0px}div#logo -a{color:black;float:left;font-size:18px;font-weight:bold;font-family:Iosevka, -Iosevka Term, Fira Mono, Inconsolata, monospace;text-decoration:none}div > -span.kw{color:#007020}div > span.type{color:#902000}div#header -#navigation{text-align:right}div#header #navigation -a{color:black;font-size:18px;font-weight:bold;margin-left:12px;text-decoration:none;text-transform:uppercase}div#footer{border-top:solid -2px black;color:#555;font-size:12px;margin-top:30px;padding:12px 0px 12px -0px;text-align:right}div#content{text-align:justify;text-justify:inter-word}h1{font-size:24px}h2{font-size:20px}div.info{color:#555;font-size:14px;font-style:italic} diff --git a/static/icon/android-chrome-192x192.png b/static/icon/android-chrome-192x192.png index 3d6fecf..f91e336 100644 Binary files a/static/icon/android-chrome-192x192.png and b/static/icon/android-chrome-192x192.png differ diff --git a/static/icon/android-chrome-512x512.png b/static/icon/android-chrome-512x512.png index 9afb502..39c6c42 100644 Binary files a/static/icon/android-chrome-512x512.png and b/static/icon/android-chrome-512x512.png differ diff --git a/static/icon/apple-touch-icon.png b/static/icon/apple-touch-icon.png index 7a0187d..f7be2ef 100644 Binary files a/static/icon/apple-touch-icon.png and b/static/icon/apple-touch-icon.png differ diff --git a/static/icon/cube-128x.png b/static/icon/cube-128x.png new file mode 100644 index 0000000..1365f59 Binary files /dev/null and b/static/icon/cube-128x.png differ diff --git a/static/icon/favicon-16x16.png b/static/icon/favicon-16x16.png index 4430f66..54fb1cc 100644 Binary files a/static/icon/favicon-16x16.png and b/static/icon/favicon-16x16.png differ diff --git a/static/icon/favicon-32x32.png b/static/icon/favicon-32x32.png index 8feaa12..9b522a3 100644 Binary files a/static/icon/favicon-32x32.png and b/static/icon/favicon-32x32.png differ diff --git a/static/icon/favicon.ico b/static/icon/favicon.ico index 0920989..f9cba75 100644 Binary files a/static/icon/favicon.ico and b/static/icon/favicon.ico differ diff --git a/static/icon/pfp-alt.png b/static/icon/pfp-alt.png deleted file mode 100644 index f11b08d..0000000 Binary files a/static/icon/pfp-alt.png and /dev/null differ diff --git a/static/icon/pfp-alt@128.png b/static/icon/pfp-alt@128.png deleted file mode 100644 index 165d1a0..0000000 Binary files a/static/icon/pfp-alt@128.png and /dev/null differ diff --git a/static/icon/pfp-alt@256.png b/static/icon/pfp-alt@256.png deleted file mode 100644 index 665a6c7..0000000 Binary files a/static/icon/pfp-alt@256.png and /dev/null differ diff --git a/static/icon/pfp-alt@512.png b/static/icon/pfp-alt@512.png deleted file mode 100644 index 374a5d1..0000000 Binary files a/static/icon/pfp-alt@512.png and /dev/null differ diff --git a/static/icon/pfp-alt@96.png b/static/icon/pfp-alt@96.png deleted file mode 100644 index f9e1e39..0000000 Binary files a/static/icon/pfp-alt@96.png and /dev/null differ diff --git a/static/icon/pfp-tired.png b/static/icon/pfp-tired.png deleted file mode 100644 index 0a94151..0000000 Binary files a/static/icon/pfp-tired.png and /dev/null differ diff --git a/static/icon/pfp-tired@128.png b/static/icon/pfp-tired@128.png deleted file mode 100644 index 8083b01..0000000 Binary files a/static/icon/pfp-tired@128.png and /dev/null differ diff --git a/static/icon/pfp-tired@256.png b/static/icon/pfp-tired@256.png deleted file mode 100644 index ba8d842..0000000 Binary files a/static/icon/pfp-tired@256.png and /dev/null differ diff --git a/static/icon/pfp-tired@512.png b/static/icon/pfp-tired@512.png deleted file mode 100644 index d89a3e6..0000000 Binary files a/static/icon/pfp-tired@512.png and /dev/null differ diff --git a/static/icon/pfp-tired@96.png b/static/icon/pfp-tired@96.png deleted file mode 100644 index b56f8a8..0000000 Binary files a/static/icon/pfp-tired@96.png and /dev/null differ diff --git a/static/icon/pfp.jpg b/static/icon/pfp.jpg index 93a9400..a3cf90e 100644 Binary files a/static/icon/pfp.jpg and b/static/icon/pfp.jpg differ diff --git a/static/icon/pfp.png b/static/icon/pfp.png index b93d19f..db9ec9b 100644 Binary files a/static/icon/pfp.png and b/static/icon/pfp.png differ diff --git a/static/icon/pfp@128.png b/static/icon/pfp@128.png index 5eef715..d7d8088 100644 Binary files a/static/icon/pfp@128.png and b/static/icon/pfp@128.png differ diff --git a/static/icon/pfp@256.png b/static/icon/pfp@256.png index e915907..877b699 100644 Binary files a/static/icon/pfp@256.png and b/static/icon/pfp@256.png differ diff --git a/static/icon/pfp@512.png b/static/icon/pfp@512.png index 60943b7..5c1fd64 100644 Binary files a/static/icon/pfp@512.png and b/static/icon/pfp@512.png differ diff --git a/static/icon/pfp@96.png b/static/icon/pfp@96.png index ccdb349..cde9ebc 100644 Binary files a/static/icon/pfp@96.png and b/static/icon/pfp@96.png differ diff --git a/static/licenses/LICENSE.FantasqueSansMono b/static/licenses/LICENSE.FantasqueSansMono deleted file mode 100644 index af9106f..0000000 --- a/static/licenses/LICENSE.FantasqueSansMono +++ /dev/null @@ -1,93 +0,0 @@ -Copyright (c) 2013-2017, Jany Belluz (jany.belluz@hotmail.fr) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/licenses/LICENSE.Iosevka b/static/licenses/LICENSE.Iosevka new file mode 100644 index 0000000..b13467d --- /dev/null +++ b/static/licenses/LICENSE.Iosevka @@ -0,0 +1,110 @@ +Copyright 2015-2021, Renzhi Li (aka. Belleve Invis, belleve@typeof.net) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +-------------------------- + + +SIL Open Font License v1.1 +==================================================== + + +Preamble +---------- + +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + + +Definitions +------------- + +`"Font Software"` refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +`"Reserved Font Name"` refers to any names specified as such after the +copyright statement(s). + +`"Original Version"` refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +`"Modified Version"` refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +`"Author"` refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + + +Permission & Conditions +------------------------ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1. Neither the Font Software nor any of its individual components, + in Original or Modified Versions, may be sold by itself. + +2. Original or Modified Versions of the Font Software may be bundled, + redistributed and/or sold with any software, provided that each copy + contains the above copyright notice and this license. These can be + included either as stand-alone text files, human-readable headers or + in the appropriate machine-readable metadata fields within text or + binary files as long as those fields can be easily viewed by the user. + +3. No Modified Version of the Font Software may use the Reserved Font + Name(s) unless explicit written permission is granted by the corresponding + Copyright Holder. This restriction only applies to the primary font name as + presented to the users. + +4. The name(s) of the Copyright Holder(s) or the Author(s) of the Font + Software shall not be used to promote, endorse or advertise any + Modified Version, except to acknowledge the contribution(s) of the + Copyright Holder(s) and the Author(s) or with their explicit written + permission. + +5. The Font Software, modified or unmodified, in part or in whole, + must be distributed entirely under this license, and must not be + distributed under any other license. The requirement for fonts to + remain under this license does not apply to any document created + using the Font Software. + + + +Termination +----------- + +This license becomes null and void if any of the above conditions are +not met. + + + DISCLAIMER + + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE + COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL + DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM + OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/licenses/LICENSE.Noto b/static/licenses/LICENSE.Noto new file mode 100644 index 0000000..bf911cf --- /dev/null +++ b/static/licenses/LICENSE.Noto @@ -0,0 +1,200 @@ + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/static/svg/amulet.svg b/static/svg/amulet.svg new file mode 100644 index 0000000..90b5543 --- /dev/null +++ b/static/svg/amulet.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/static/svg/gitea.svg b/static/svg/gitea.svg new file mode 100644 index 0000000..68594db --- /dev/null +++ b/static/svg/gitea.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + diff --git a/static/svg/github.svg b/static/svg/github.svg new file mode 100644 index 0000000..33a0d49 --- /dev/null +++ b/static/svg/github.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/svg/kofi.svg b/static/svg/kofi.svg new file mode 100644 index 0000000..8d9a658 --- /dev/null +++ b/static/svg/kofi.svg @@ -0,0 +1,46 @@ + + + + + + + + + diff --git a/static/svg/twitter.svg b/static/svg/twitter.svg new file mode 100644 index 0000000..c8342b6 --- /dev/null +++ b/static/svg/twitter.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/ttf/iosevk-abbie-bold.ttf b/static/ttf/iosevk-abbie-bold.ttf new file mode 100644 index 0000000..85db838 Binary files /dev/null and b/static/ttf/iosevk-abbie-bold.ttf differ diff --git a/static/ttf/iosevk-abbie-bolditalic.ttf b/static/ttf/iosevk-abbie-bolditalic.ttf new file mode 100644 index 0000000..12b31ef Binary files /dev/null and b/static/ttf/iosevk-abbie-bolditalic.ttf differ diff --git a/static/ttf/iosevk-abbie-boldoblique.ttf b/static/ttf/iosevk-abbie-boldoblique.ttf new file mode 100644 index 0000000..d9ce3e7 Binary files /dev/null and b/static/ttf/iosevk-abbie-boldoblique.ttf differ diff --git a/static/ttf/iosevk-abbie-extended.ttf b/static/ttf/iosevk-abbie-extended.ttf new file mode 100644 index 0000000..d687f8b Binary files /dev/null and b/static/ttf/iosevk-abbie-extended.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedbold.ttf b/static/ttf/iosevk-abbie-extendedbold.ttf new file mode 100644 index 0000000..49a9e10 Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedbold.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedbolditalic.ttf b/static/ttf/iosevk-abbie-extendedbolditalic.ttf new file mode 100644 index 0000000..f4d057d Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedbolditalic.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedboldoblique.ttf b/static/ttf/iosevk-abbie-extendedboldoblique.ttf new file mode 100644 index 0000000..e912ab0 Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedboldoblique.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedextrabold.ttf b/static/ttf/iosevk-abbie-extendedextrabold.ttf new file mode 100644 index 0000000..4dfe62f Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedextrabold.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedextrabolditalic.ttf b/static/ttf/iosevk-abbie-extendedextrabolditalic.ttf new file mode 100644 index 0000000..49ed186 Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedextrabolditalic.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedextraboldoblique.ttf b/static/ttf/iosevk-abbie-extendedextraboldoblique.ttf new file mode 100644 index 0000000..acc1ca0 Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedextraboldoblique.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedheavy.ttf b/static/ttf/iosevk-abbie-extendedheavy.ttf new file mode 100644 index 0000000..77ba995 Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedheavy.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedheavyitalic.ttf b/static/ttf/iosevk-abbie-extendedheavyitalic.ttf new file mode 100644 index 0000000..5c92346 Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedheavyitalic.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedheavyoblique.ttf b/static/ttf/iosevk-abbie-extendedheavyoblique.ttf new file mode 100644 index 0000000..03dfdc2 Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedheavyoblique.ttf differ diff --git a/static/ttf/iosevk-abbie-extendeditalic.ttf b/static/ttf/iosevk-abbie-extendeditalic.ttf new file mode 100644 index 0000000..0094a3b Binary files /dev/null and b/static/ttf/iosevk-abbie-extendeditalic.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedmedium.ttf b/static/ttf/iosevk-abbie-extendedmedium.ttf new file mode 100644 index 0000000..764d0e1 Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedmedium.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedmediumitalic.ttf b/static/ttf/iosevk-abbie-extendedmediumitalic.ttf new file mode 100644 index 0000000..52e40a7 Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedmediumitalic.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedmediumoblique.ttf b/static/ttf/iosevk-abbie-extendedmediumoblique.ttf new file mode 100644 index 0000000..068bac4 Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedmediumoblique.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedoblique.ttf b/static/ttf/iosevk-abbie-extendedoblique.ttf new file mode 100644 index 0000000..1ccd63e Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedoblique.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedsemibold.ttf b/static/ttf/iosevk-abbie-extendedsemibold.ttf new file mode 100644 index 0000000..1e5c5ed Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedsemibold.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedsemibolditalic.ttf b/static/ttf/iosevk-abbie-extendedsemibolditalic.ttf new file mode 100644 index 0000000..efe8106 Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedsemibolditalic.ttf differ diff --git a/static/ttf/iosevk-abbie-extendedsemiboldoblique.ttf b/static/ttf/iosevk-abbie-extendedsemiboldoblique.ttf new file mode 100644 index 0000000..ed7b9ee Binary files /dev/null and b/static/ttf/iosevk-abbie-extendedsemiboldoblique.ttf differ diff --git a/static/ttf/iosevk-abbie-extrabold.ttf b/static/ttf/iosevk-abbie-extrabold.ttf new file mode 100644 index 0000000..4820ea6 Binary files /dev/null and b/static/ttf/iosevk-abbie-extrabold.ttf differ diff --git a/static/ttf/iosevk-abbie-extrabolditalic.ttf b/static/ttf/iosevk-abbie-extrabolditalic.ttf new file mode 100644 index 0000000..66da859 Binary files /dev/null and b/static/ttf/iosevk-abbie-extrabolditalic.ttf differ diff --git a/static/ttf/iosevk-abbie-extraboldoblique.ttf b/static/ttf/iosevk-abbie-extraboldoblique.ttf new file mode 100644 index 0000000..84bbda2 Binary files /dev/null and b/static/ttf/iosevk-abbie-extraboldoblique.ttf differ diff --git a/static/ttf/iosevk-abbie-heavy.ttf b/static/ttf/iosevk-abbie-heavy.ttf new file mode 100644 index 0000000..8eaaf4e Binary files /dev/null and b/static/ttf/iosevk-abbie-heavy.ttf differ diff --git a/static/ttf/iosevk-abbie-heavyitalic.ttf b/static/ttf/iosevk-abbie-heavyitalic.ttf new file mode 100644 index 0000000..554119c Binary files /dev/null and b/static/ttf/iosevk-abbie-heavyitalic.ttf differ diff --git a/static/ttf/iosevk-abbie-heavyoblique.ttf b/static/ttf/iosevk-abbie-heavyoblique.ttf new file mode 100644 index 0000000..d99c6e6 Binary files /dev/null and b/static/ttf/iosevk-abbie-heavyoblique.ttf differ diff --git a/static/ttf/iosevk-abbie-italic.ttf b/static/ttf/iosevk-abbie-italic.ttf new file mode 100644 index 0000000..417a8d8 Binary files /dev/null and b/static/ttf/iosevk-abbie-italic.ttf differ diff --git a/static/ttf/iosevk-abbie-medium.ttf b/static/ttf/iosevk-abbie-medium.ttf new file mode 100644 index 0000000..c22be8d Binary files /dev/null and b/static/ttf/iosevk-abbie-medium.ttf differ diff --git a/static/ttf/iosevk-abbie-mediumitalic.ttf b/static/ttf/iosevk-abbie-mediumitalic.ttf new file mode 100644 index 0000000..29e85ea Binary files /dev/null and b/static/ttf/iosevk-abbie-mediumitalic.ttf differ diff --git a/static/ttf/iosevk-abbie-mediumoblique.ttf b/static/ttf/iosevk-abbie-mediumoblique.ttf new file mode 100644 index 0000000..b3f8ccd Binary files /dev/null and b/static/ttf/iosevk-abbie-mediumoblique.ttf differ diff --git a/static/ttf/iosevk-abbie-oblique.ttf b/static/ttf/iosevk-abbie-oblique.ttf new file mode 100644 index 0000000..6e019e9 Binary files /dev/null and b/static/ttf/iosevk-abbie-oblique.ttf differ diff --git a/static/ttf/iosevk-abbie-regular.ttf b/static/ttf/iosevk-abbie-regular.ttf new file mode 100644 index 0000000..d60fa9b Binary files /dev/null and b/static/ttf/iosevk-abbie-regular.ttf differ diff --git a/static/ttf/iosevk-abbie-semibold.ttf b/static/ttf/iosevk-abbie-semibold.ttf new file mode 100644 index 0000000..9908e1d Binary files /dev/null and b/static/ttf/iosevk-abbie-semibold.ttf differ diff --git a/static/ttf/iosevk-abbie-semibolditalic.ttf b/static/ttf/iosevk-abbie-semibolditalic.ttf new file mode 100644 index 0000000..010157e Binary files /dev/null and b/static/ttf/iosevk-abbie-semibolditalic.ttf differ diff --git a/static/ttf/iosevk-abbie-semiboldoblique.ttf b/static/ttf/iosevk-abbie-semiboldoblique.ttf new file mode 100644 index 0000000..1baa57a Binary files /dev/null and b/static/ttf/iosevk-abbie-semiboldoblique.ttf differ diff --git a/static/woff2/iosevk-abbie-bold.woff2 b/static/woff2/iosevk-abbie-bold.woff2 new file mode 100644 index 0000000..c5a800d Binary files /dev/null and b/static/woff2/iosevk-abbie-bold.woff2 differ diff --git a/static/woff2/iosevk-abbie-bolditalic.woff2 b/static/woff2/iosevk-abbie-bolditalic.woff2 new file mode 100644 index 0000000..b80dc39 Binary files /dev/null and b/static/woff2/iosevk-abbie-bolditalic.woff2 differ diff --git a/static/woff2/iosevk-abbie-boldoblique.woff2 b/static/woff2/iosevk-abbie-boldoblique.woff2 new file mode 100644 index 0000000..46569b2 Binary files /dev/null and b/static/woff2/iosevk-abbie-boldoblique.woff2 differ diff --git a/static/woff2/iosevk-abbie-extended.woff2 b/static/woff2/iosevk-abbie-extended.woff2 new file mode 100644 index 0000000..6916d87 Binary files /dev/null and b/static/woff2/iosevk-abbie-extended.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedbold.woff2 b/static/woff2/iosevk-abbie-extendedbold.woff2 new file mode 100644 index 0000000..bf8badc Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedbold.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedbolditalic.woff2 b/static/woff2/iosevk-abbie-extendedbolditalic.woff2 new file mode 100644 index 0000000..20805dc Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedbolditalic.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedboldoblique.woff2 b/static/woff2/iosevk-abbie-extendedboldoblique.woff2 new file mode 100644 index 0000000..c834e03 Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedboldoblique.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedextrabold.woff2 b/static/woff2/iosevk-abbie-extendedextrabold.woff2 new file mode 100644 index 0000000..8b1941c Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedextrabold.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedextrabolditalic.woff2 b/static/woff2/iosevk-abbie-extendedextrabolditalic.woff2 new file mode 100644 index 0000000..057ff1d Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedextrabolditalic.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedextraboldoblique.woff2 b/static/woff2/iosevk-abbie-extendedextraboldoblique.woff2 new file mode 100644 index 0000000..07fed79 Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedextraboldoblique.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedheavy.woff2 b/static/woff2/iosevk-abbie-extendedheavy.woff2 new file mode 100644 index 0000000..42c5223 Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedheavy.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedheavyitalic.woff2 b/static/woff2/iosevk-abbie-extendedheavyitalic.woff2 new file mode 100644 index 0000000..b2f0abc Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedheavyitalic.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedheavyoblique.woff2 b/static/woff2/iosevk-abbie-extendedheavyoblique.woff2 new file mode 100644 index 0000000..b082e48 Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedheavyoblique.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendeditalic.woff2 b/static/woff2/iosevk-abbie-extendeditalic.woff2 new file mode 100644 index 0000000..5dd5dc6 Binary files /dev/null and b/static/woff2/iosevk-abbie-extendeditalic.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedmedium.woff2 b/static/woff2/iosevk-abbie-extendedmedium.woff2 new file mode 100644 index 0000000..443d15c Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedmedium.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedmediumitalic.woff2 b/static/woff2/iosevk-abbie-extendedmediumitalic.woff2 new file mode 100644 index 0000000..9312713 Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedmediumitalic.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedmediumoblique.woff2 b/static/woff2/iosevk-abbie-extendedmediumoblique.woff2 new file mode 100644 index 0000000..30a3843 Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedmediumoblique.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedoblique.woff2 b/static/woff2/iosevk-abbie-extendedoblique.woff2 new file mode 100644 index 0000000..4557c41 Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedoblique.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedsemibold.woff2 b/static/woff2/iosevk-abbie-extendedsemibold.woff2 new file mode 100644 index 0000000..cd41ee0 Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedsemibold.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedsemibolditalic.woff2 b/static/woff2/iosevk-abbie-extendedsemibolditalic.woff2 new file mode 100644 index 0000000..2a3228e Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedsemibolditalic.woff2 differ diff --git a/static/woff2/iosevk-abbie-extendedsemiboldoblique.woff2 b/static/woff2/iosevk-abbie-extendedsemiboldoblique.woff2 new file mode 100644 index 0000000..c41498d Binary files /dev/null and b/static/woff2/iosevk-abbie-extendedsemiboldoblique.woff2 differ diff --git a/static/woff2/iosevk-abbie-extrabold.woff2 b/static/woff2/iosevk-abbie-extrabold.woff2 new file mode 100644 index 0000000..5d21d6a Binary files /dev/null and b/static/woff2/iosevk-abbie-extrabold.woff2 differ diff --git a/static/woff2/iosevk-abbie-extrabolditalic.woff2 b/static/woff2/iosevk-abbie-extrabolditalic.woff2 new file mode 100644 index 0000000..7be709b Binary files /dev/null and b/static/woff2/iosevk-abbie-extrabolditalic.woff2 differ diff --git a/static/woff2/iosevk-abbie-extraboldoblique.woff2 b/static/woff2/iosevk-abbie-extraboldoblique.woff2 new file mode 100644 index 0000000..0a2b1e9 Binary files /dev/null and b/static/woff2/iosevk-abbie-extraboldoblique.woff2 differ diff --git a/static/woff2/iosevk-abbie-heavy.woff2 b/static/woff2/iosevk-abbie-heavy.woff2 new file mode 100644 index 0000000..2aa1de6 Binary files /dev/null and b/static/woff2/iosevk-abbie-heavy.woff2 differ diff --git a/static/woff2/iosevk-abbie-heavyitalic.woff2 b/static/woff2/iosevk-abbie-heavyitalic.woff2 new file mode 100644 index 0000000..d348b19 Binary files /dev/null and b/static/woff2/iosevk-abbie-heavyitalic.woff2 differ diff --git a/static/woff2/iosevk-abbie-heavyoblique.woff2 b/static/woff2/iosevk-abbie-heavyoblique.woff2 new file mode 100644 index 0000000..7bdd72e Binary files /dev/null and b/static/woff2/iosevk-abbie-heavyoblique.woff2 differ diff --git a/static/woff2/iosevk-abbie-italic.woff2 b/static/woff2/iosevk-abbie-italic.woff2 new file mode 100644 index 0000000..30ebec0 Binary files /dev/null and b/static/woff2/iosevk-abbie-italic.woff2 differ diff --git a/static/woff2/iosevk-abbie-medium.woff2 b/static/woff2/iosevk-abbie-medium.woff2 new file mode 100644 index 0000000..42354f4 Binary files /dev/null and b/static/woff2/iosevk-abbie-medium.woff2 differ diff --git a/static/woff2/iosevk-abbie-mediumitalic.woff2 b/static/woff2/iosevk-abbie-mediumitalic.woff2 new file mode 100644 index 0000000..68bed1a Binary files /dev/null and b/static/woff2/iosevk-abbie-mediumitalic.woff2 differ diff --git a/static/woff2/iosevk-abbie-mediumoblique.woff2 b/static/woff2/iosevk-abbie-mediumoblique.woff2 new file mode 100644 index 0000000..699eb5d Binary files /dev/null and b/static/woff2/iosevk-abbie-mediumoblique.woff2 differ diff --git a/static/woff2/iosevk-abbie-oblique.woff2 b/static/woff2/iosevk-abbie-oblique.woff2 new file mode 100644 index 0000000..8903d9e Binary files /dev/null and b/static/woff2/iosevk-abbie-oblique.woff2 differ diff --git a/static/woff2/iosevk-abbie-regular.woff2 b/static/woff2/iosevk-abbie-regular.woff2 new file mode 100644 index 0000000..89e3c8f Binary files /dev/null and b/static/woff2/iosevk-abbie-regular.woff2 differ diff --git a/static/woff2/iosevk-abbie-semibold.woff2 b/static/woff2/iosevk-abbie-semibold.woff2 new file mode 100644 index 0000000..f0d8b5f Binary files /dev/null and b/static/woff2/iosevk-abbie-semibold.woff2 differ diff --git a/static/woff2/iosevk-abbie-semibolditalic.woff2 b/static/woff2/iosevk-abbie-semibolditalic.woff2 new file mode 100644 index 0000000..53dc703 Binary files /dev/null and b/static/woff2/iosevk-abbie-semibolditalic.woff2 differ diff --git a/static/woff2/iosevk-abbie-semiboldoblique.woff2 b/static/woff2/iosevk-abbie-semiboldoblique.woff2 new file mode 100644 index 0000000..0988841 Binary files /dev/null and b/static/woff2/iosevk-abbie-semiboldoblique.woff2 differ diff --git a/sync b/sync index df2aca6..b4d77a9 100755 --- a/sync +++ b/sync @@ -1,3 +1,3 @@ #!/usr/bin/env bash -rsync .site/ "ahti:/home/abby/abby.how" -vuar0 +rsync .site/ "shamiko:/var/www/amelia.how" -avx \ No newline at end of file diff --git a/templates/default.html b/templates/default.html index 11ac157..6c710cb 100644 --- a/templates/default.html +++ b/templates/default.html @@ -10,19 +10,19 @@ - + - + @@ -36,7 +36,7 @@
-

$title$

+
+

$title$

+ $if(subtitle)$ +
+

$subtitle$

+
+ $endif$ +
$body$
diff --git a/templates/post.html b/templates/post.html index df0072e..9ccef85 100644 --- a/templates/post.html +++ b/templates/post.html @@ -1,7 +1,9 @@
@@ -10,6 +12,4 @@
$body$
-
- -
\ No newline at end of file +
\ No newline at end of file diff --git a/test.dot b/test.dot deleted file mode 100644 index 073ddbd..0000000 --- a/test.dot +++ /dev/null @@ -1,3 +0,0 @@ -digraph G { - stack -> 3628800 -}